You are on page 1of 227

Wicket user guide

by Andrea Del Bene (an.delbene@gmail.com) proof reading by Paul Bors (paul@bors.ws) Revision date: 2013-05-30

A free guide to Apache Wicket

License
This document is licensed under the Attribution- on!ommercial-"hareAli#e $.% &nported 'ou are free( to "hare ) to copy* distribute and transmit the wor# to +emi, ) to adapt the wor# &nder the following conditions( Attribution ) 'ou must attribute the wor# in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the wor#). oncommercial ) 'ou may not use this wor# for commercial purposes. "hare Ali#e ) -f you alter* transform* or build upon this wor#* you may distribute the resulting wor# only under the same or similar license to this one. The full license is a.ailable at http(//creati.ecommons.org/licenses/by-nc-sa/$.%/.

We should invent a miracle...yes, we should get to the point where our egoism magically coincides with the happiness of others. -0iorgio 0aber* singer* poet and actor.

Table of Contents

Table of !ontents
Preface..................................................................................................................................... 1 How to use the example code................................................................................................2 Graphic conventions.............................................................................................................. 3 1 Wh should ! learn Wicket".................................................................................................#
1.1 2e all li#e spaghetti (-) ..................................................................................................................................... 3 1.4 !omponent oriented framewor#s( an o.er.iew.................................................................................................3 1.$ Benefits of component oriented framewor#s for web de.elopment...................................................................5 1.3 2ic#et .s the other component oriented framewor#s.......................................................................................5

2 Wicket sa s $Hello world%&..................................................................................................'


4.1 2ic#et distribution and modules........................................................................................................................ 6 4.4 !onfiguration of 2ic#et applications................................................................................................................. 7 4.4.1 2ic#et application structure...................................................................................................................... 7 4.4.4 The application class................................................................................................................................ 8 4.$ The 9omePage class...................................................................................................................................... 11 4.3 2ic#et :in#s.................................................................................................................................................... 14 4.5 "ummary......................................................................................................................................................... 1$

3 Wicket as page la out manager.........................................................................................1(


$.1 9eader* footer* left menu* content* etc............................................................................................................15 $.4 9ere comes the inheritance;........................................................................................................................... 16 $.4.1 <ar#up inheritance................................................................................................................................. 16 $.4.4 Panel class............................................................................................................................................. 17 $.$ Di.ide et impera;............................................................................................................................................. 4% $.$.1 Panels and layout areas......................................................................................................................... 4% $.$.4 Template page........................................................................................................................................ 41 $.$.$ =inal e,ample......................................................................................................................................... 41 $.3 <ar#up inheritance with the >wic#et(e,tend? tag ..........................................................................................4$ $.3.1 @ur e,ample re.isited............................................................................................................................. 43 $.5 "ummary......................................................................................................................................................... 45

# )eeping control over H*+,...............................................................................................23.1 9iding or disabling a component..................................................................................................................... 4A 3.4 <odifing tag attributes..................................................................................................................................... 4A 3.$ 0enerating tag attribute BidB ............................................................................................................................ 46 3.3 !reating in-line panels with 2eb<ar#up!ontainer.........................................................................................46 3.5 2or#ing with mar#up fragments...................................................................................................................... 47 3.A Adding header contents to the final page........................................................................................................48 3.6 &sing stub mar#up in our pages/panels..........................................................................................................$% 3.7 9ow to render component body only...............................................................................................................$% 3.8 9iding decorating elements with the >wic#et(enclosure? tag..........................................................................$1 3.1% "urrounding e,isting mar#up with Border.....................................................................................................$4 3.11 "ummary....................................................................................................................................................... $$

( .omponents lifec cle.........................................................................................................3(


5.1 :ifecycle stages of a component..................................................................................................................... $5 5.4 9oo# methods for component lifecycle...........................................................................................................$5 5.$ -nitialiCation stage............................................................................................................................................ $A 5.3 +endering stage.............................................................................................................................................. $A 5.3.1 <ethod on!onfigure............................................................................................................................... $A 5.3.4 <ethod onBefore+ender........................................................................................................................ $A 5.3.$ <ethod on!omponentTag...................................................................................................................... $6 5.3.3 <ethods on!omponentTagBody............................................................................................................$7 5.5 +emo.ing stage.............................................................................................................................................. $8 5.A "ummary......................................................................................................................................................... $8

- Page versioning and caching............................................................................................#/


A.1 "tateful pages D" stateless............................................................................................................................ 3% A.4 "tateful pages................................................................................................................................................. 3% A.4.1 &sing a specific page .ersion with Page+eference................................................................................34 A.4.4 Turning off page .ersioning.................................................................................................................... 34 A.4.$ Pluggable serialiCation............................................................................................................................ 34 A.4.3 Page caching.......................................................................................................................................... 3$ A.4.5 Page e,piration....................................................................................................................................... 3$ A.$ "tateless pages............................................................................................................................................... 33

Wicket free user guide

Table of Contents

A.3 "ummary......................................................................................................................................................... 35

' 0nder the hood of the re1uest processing.......................................................................#6.1 !lass Application and reEuest processing......................................................................................................3A 6.4 +eEuest and +esponse classes..................................................................................................................... 3A 6.$ The FdirectorG of reEuest processing( +eEuest!ycle.......................................................................................3A 6.$.1 +eEuest!ycle and reEuest processing...................................................................................................36 6.$.4 0enerating &+: with the url=or and map&rl=or methods......................................................................37 6.$.$ <ethod set+esponsePage..................................................................................................................... 37 6.$.3 +eEuest!ycleBs hoo# methods and listeners..........................................................................................37 6.3 "ession !lass.................................................................................................................................................. 38 6.3.1 "ession and listeners.............................................................................................................................. 38 6.3.4 9andling session attributes..................................................................................................................... 5% 6.3.$ Accessing to the 9TTP session..............................................................................................................5% 6.3.3 Temporary and permanent sessions......................................................................................................51 6.3.5 Discarding session data.......................................................................................................................... 54 6.5 "toring arbitrary obHects with metadata...........................................................................................................54 6.A "ummary......................................................................................................................................................... 5$

2 Wicket ,inks and 03, generation.....................................................................................(#


7.1 PageParameters............................................................................................................................................. 53 7.1.1 PageParameters and boo#mar#able pages...........................................................................................53 7.1.4 -nde,ed parameters................................................................................................................................ 55 7.4 Boo#mar#able lin#s......................................................................................................................................... 5A 7.$ Automatically creating boo#mar#able lin#s with tag >wic#et(lin#?..................................................................5A 7.3 I,ternal lin#s................................................................................................................................................... 57 7.5 "tateless lin#s................................................................................................................................................. 58 7.A 0enerating structured and clear &+:s............................................................................................................58 7.A.1 <ounting a single page........................................................................................................................... A% 7.A.4 &sing parameter placeholders with mounted pages...............................................................................A% 7.A.$ <ounting a pac#age............................................................................................................................... A1 7.A.3 Pro.iding custom mapper conte,t to reEuest mappers..........................................................................A1 7.A.5 !ontrolling how page parameters are encoded with -PageParametersIncoder....................................A4 7.A.A Incrypting page &+:s............................................................................................................................ A$ 7.6 "ummary......................................................................................................................................................... A3

4 Wicket models and forms..................................................................................................-(


8.1 2hat is a modelJ............................................................................................................................................. A5 8.4 <odels and Ka.aBeans................................................................................................................................... A6 8.4.1 Property<odel........................................................................................................................................ A7 8.4.4 !ompoundProperty<odel and model inheritance..................................................................................A7 8.$ 2ic#et forms.................................................................................................................................................... 6% 8.$.1 =orm and models.................................................................................................................................... 6% 8.$.4 :ogin form............................................................................................................................................... 61 8.3 !omponent DropDown!hoice........................................................................................................................ 63 8.5 <odel chaining................................................................................................................................................ 65 8.A Detachable models.......................................................................................................................................... 67 8.6 &sing more than one model in a component...................................................................................................7% 8.7 &se models;.................................................................................................................................................... 71 8.8 "ummary......................................................................................................................................................... 71

1/ Wicket forms in detail.......................................................................................................22


1%.1 Default form processing................................................................................................................................ 74 1%.4 =orm .alidation and feedbac# messages......................................................................................................74 1%.4.1 =eedbac# messages and localiCation...................................................................................................7$ 1%.4.4 Displaing feedbac# messages and filtering them.................................................................................73 1%.4.$ Built-in .alidators.................................................................................................................................. 73 1%.4.3 @.erriding standard feedbac# messages with custom bundles............................................................7A 1%.4.5 !reating custom .alidators................................................................................................................... 7A 1%.4.A &sing flash messages........................................................................................................................... 76 1%.$ -nput .alue con.ersion.................................................................................................................................. 78 1%.$.1 !reating custom application-scoped con.erters..................................................................................8% 1%.3 "ubmit form with an -=orm"ubmitting!omponent.........................................................................................84 1%.3.1 !omponents Button and "ubmit:in#....................................................................................................8$ 1%.3.4 Disabling default form processing.........................................................................................................85 1%.5 ested forms................................................................................................................................................. 85 1%.A <ulti-line te,t input........................................................................................................................................ 85 1%.6 =ile upload .................................................................................................................................................... 8A 1%.6.1 &pload multiple files.............................................................................................................................. 86

Wicket free user guide

ii

Table of Contents

1%.7 !reating comple, form components with =orm!omponentPanel.................................................................86 1%.8 "tateless form............................................................................................................................................. 1%% 1%.1% 2or#ing with radio buttons and chec#bo,es.............................................................................................1%4 1%.1%.1 2or#ing with grouped chec#bo,es...................................................................................................1%3 1%.1%.4 9ow to implement a F"elect allG chec#bo,........................................................................................1%5 1%.1%.$ 2or#ing with grouped radio buttons.................................................................................................1%A 1%.11 "electing multiple .alues with :ist<ultiple!hoices and Palette ...............................................................1%A 1%.11.1 !omponent Palette........................................................................................................................... 1%6 1%.14 "ummary................................................................................................................................................... 1%8

11 5ispla ing multiple items with repeaters......................................................................11/


11.1 !omponent +epeatingDiew......................................................................................................................... 11% 11.4 !omponent :istDiew................................................................................................................................... 111 11.4.1 :istDiew and =orm.............................................................................................................................. 114 11.$ !omponent +efreshingDiew........................................................................................................................ 114 11.$.1 -tem reuse strategy............................................................................................................................. 11$ 11.3 Pageable repeaters..................................................................................................................................... 11$ 11.3.1 !omponent DataDiew......................................................................................................................... 11$ 11.3.4 Data paging........................................................................................................................................ 113 11.5 "ummary..................................................................................................................................................... 115

12 !nternationali6ation with Wicket.....................................................................................11'


14.1 :ocaliCation................................................................................................................................................. 116 14.4 !lass :ocale and +esourceBundle.............................................................................................................116 14.$ :ocaliCation in 2ic#et.................................................................................................................................. 117 14.$.1 "tyle and .ariation parameters for bundles........................................................................................118 14.$.4 &sing L<: files as resource bundles.................................................................................................118 14.$.$ +eading bundles from code................................................................................................................14% 14.$.3 :ocaliCation of bundles in 2ic#et........................................................................................................14% 14.$.5 :ocaliCation of mar#up files................................................................................................................141 14.$.A +eading bundles with tag >wic#et(message?.....................................................................................141 14.3 Bundles loo#up algorithm............................................................................................................................ 144 14.3.1 :ocaliCing pages and panels..............................................................................................................144 14.3.4 !omponent-specific resources...........................................................................................................14$ 14.3.$ Pac#age bundles................................................................................................................................ 143 14.3.3 Bundles for feedbac# messages.........................................................................................................143 14.3.5 I,tending the default loo#up algorithm...............................................................................................145 14.5 :ocaliCation of componentBs choices...........................................................................................................145 14.A -nternationaliCation and <odels................................................................................................................... 14A 14.A.1 +esource<odel................................................................................................................................... 146 14.A.4 "tring+esource<odel......................................................................................................................... 146 14.6 "ummary..................................................................................................................................................... 147

13 3esource management with Wicket..............................................................................13/


1$.1 "tatic .s dynamic resources........................................................................................................................1$% 1$.4 +esource references................................................................................................................................... 1$% 1$.$ Pac#age resources...................................................................................................................................... 1$% 1$.$.1 &sing pac#age resources with tag >wic#et(lin#? ...............................................................................1$4 1$.3 Adding resources to page header section...................................................................................................1$$ 1$.5 +esource dependencies.............................................................................................................................. 1$3 1$.A !ustom resources....................................................................................................................................... 1$3 1$.6 <ounting resources..................................................................................................................................... 1$5 1$.7 "hared resources........................................................................................................................................ 1$A 1$.8 !ustomiCing resource loading..................................................................................................................... 1$6 1$.1% "ummary................................................................................................................................................... 1$8

1# An example of integration with 7ava8cript...................................................................1#/


13.1 2hat we want to do..................................................................................................................................... 13% 13.1.1 2hat features we want to implement..................................................................................................13% 13.4 ...and how we will do it................................................................................................................................ 131 13.4.1 !omponent pac#age resources .........................................................................................................131 13.4.4 -nitialiCation code................................................................................................................................ 134 13.4.$ 9eader contributor code.....................................................................................................................13$ 13.$ "ummary..................................................................................................................................................... 133

1( Wicket advanced topics.................................................................................................1#(


15.1 Inriching components with beha.iors.........................................................................................................135 15.4 0enerating callbac# &+:s with -+eEuest:istener.......................................................................................13A 15.$ 2ic#et e.ents infrastructure........................................................................................................................137 15.3 -nitialiCers.................................................................................................................................................... 15%
Wicket free user guide

iii

Table of Contents

15.5 &sing K<L with 2ic#et................................................................................................................................ 15% 15.A 0enerating 9T<: mar#up from code..........................................................................................................154 15.A.1 A.oiding mar#up caching....................................................................................................................15$ 15.6 "ummary..................................................................................................................................................... 153

1- Working with A7A9.........................................................................................................1((


1A.1 9ow to use AKAL components and beha.iors............................................................................................155 1A.4 Built-in AKAL components...........................................................................................................................15A 1A.4.1 :in#s and buttons................................................................................................................................ 15A 1A.4.4 =allbac# components.......................................................................................................................... 15A 1A.4.$ AKAL !hec#bo,.................................................................................................................................. 156 1A.4.3 AKAL editable labels........................................................................................................................... 156 1A.4.5 Autocomplete te,t field....................................................................................................................... 157 1A.4.A <odal window..................................................................................................................................... 157 1A.4.6 Tree repeaters.................................................................................................................................... 1A% 1A.4.7 2or#ing with hidden components.......................................................................................................1A5 1A.$ Built-in AKAL beha.iors...............................................................................................................................1A5 1A.$.1 AHa,I.entBeha.ior............................................................................................................................. 1A5 1A.$.4 AHa,=orm"ubmitBeha.ior................................................................................................................... 1A6 1A.$.$ AHa,=orm!omponent&pdatingBeha.ior.............................................................................................1A6 1A.$.3 AbstractAHa,TimerBeha.ior................................................................................................................ 1A6 1A.3 &sing an acti.ity indicator............................................................................................................................1A7 1A.5 AHa, reEuest attributes and call listeners.....................................................................................................1A7 1A.A !reating custom AKAL call listener.............................................................................................................16% 1A.A.1 2hat we want for our listener.............................................................................................................16% 1A.A.4 9ow to implement the listener............................................................................................................161 1A.A.$ Ka.a"cript code.................................................................................................................................. 161 1A.A.3 !lass code.......................................................................................................................................... 164 1A.A.5 0lobal listeners................................................................................................................................... 16$ 1A.6 "ummary..................................................................................................................................................... 163

1' !ntegration with enterprise containers..........................................................................1'(


16.1 -ntegrating 2ic#et with IKB.........................................................................................................................165 16.4 -ntegrating 2ic#et with "pring.....................................................................................................................16A 16.$ K"+-$$% annotations................................................................................................................................... 166 16.3 "ummary..................................................................................................................................................... 167

12 8ecurit with Wicket.......................................................................................................1'4


17.1 Authentication.............................................................................................................................................. 168 17.1.1 Authenticated2eb"ession..................................................................................................................168 17.1.4 Authenticated2ebApplication.............................................................................................................17% 17.1.$ A basic e,ample of authentication......................................................................................................17% 17.1.3 +edirecting user to an intermediate page...........................................................................................174 17.4 AuthoriCations.............................................................................................................................................. 17$ 17.4.1 "implePageAuthoriCation"trategy......................................................................................................173 17.4.4 +ole-based strategies......................................................................................................................... 173 17.4.4.1 &sing roles with metadata..........................................................................................................175 17.4.4.4 &sing roles with annotations......................................................................................................176 17.4.$ !atching an unauthoriCed component instantiation............................................................................177 17.4.3 "trategy +oleAuthoriCation"trategy....................................................................................................178 17.$ &sing 9TTP" protocol................................................................................................................................. 178 17.3 Pac#age +esource 0uard...........................................................................................................................18% 17.5 "ummary..................................................................................................................................................... 181

14 *est 5riven 5evelopment with Wicket..........................................................................142


18.1 &tility class 2ic#etTester............................................................................................................................ 184 18.1.1 Testing lin#s ....................................................................................................................................... 18$ 18.1.4 Testing component status...................................................................................................................183 18.1.$ Testing components in isolation.........................................................................................................183 18.1.3 Testing the response.......................................................................................................................... 183 18.1.5 Testing &+:s...................................................................................................................................... 185 18.1.A Testing AKAL components................................................................................................................. 185 18.1.6 Testing AKAL e.ents.......................................................................................................................... 185 18.1.7 Testing AKAL beha.iors..................................................................................................................... 18A 18.1.8 &sing a custom ser.let conte,t...........................................................................................................186 18.4 Testing 2ic#et forms................................................................................................................................... 186 18.4.1 "etting form components input...........................................................................................................187 18.4.4 Testing feedbac# messages...............................................................................................................187 18.4.$ Testing models................................................................................................................................... 188

Wicket free user guide

i.

Table of Contents

18.$ Testing mar#up with TagTester...................................................................................................................188 18.3 "ummary..................................................................................................................................................... 4%%

Appendix A: working with +aven......................................................................................2/2


A.1"witching 2ic#et to DIP:@'<I T mode....................................................................................................4%4 A.4!reating a 2ic#et proHect from scratch and importing it into our fa.ourite -DI.............................................4%$ A.4.1=rom <a.en to our -DI......................................................................................................................... 4%$ A.4.4-mporting a <a.en proHect into our -DI.................................................................................................4%5 A.4.$"peeding up de.elopment with plugins.................................................................................................4%6

Appendix ;: pro<ect Wicket8tuff.......................................................................................2/4


B.12hat is proHect 2ic#et"tuffJ..........................................................................................................................4%8 B.4<odule tinymce.............................................................................................................................................. 4%8 B.$<odule wic#etstuff-gmap$............................................................................................................................. 41% B.3<odule wic#etstuff-googlecharts.................................................................................................................... 411 B.5<odule wic#etstuff-inmethod-grid.................................................................................................................. 414

Alpha=etical !ndex..............................................................................................................21(

Wicket free user guide

Preface

Preface
2ic#et has been around since 4%%3 and it has been an Apache proHect since 4%%6. During these years it has pro.ed to be a solid and .aluable solution for building enterprise web applications. 2ic#et core de.elopers ha.e done a wonderful Hob with this framewor# and they continue to impro.e it release after release. 9owe.er 2ic#et ne.er pro.ided a freely a.ailable documentation and e.en if you can find on -nternet many li.e e,amples and many technical articles on it (most of them at http(//www.wic#et-library.com/ and at http(//wic#etinaction.com/)* the lac# of an organiCed and freely a.ailable documentation has always been a sore point for this framewor#. ThatBs Euite an issue because many other popular framewor#s (li#e "pring* 9ibernate or "truts) offer a .ast and .ery good documentation which substantially contributed to their success. This document is not intended to be a complete reference for 2ic#et but it simply aims to be a straightforward introduction to the framewor# that should significantly reduce its learning cur.e. 2hat you will find here reflects my e,perience with 2ic#et and itBs strictly focused on the framewor#. The .arious 2ic#et-related topics are gradually introduced using pragmatic e,amples of code that you can find at https(//github.com/bitstorm/2ic#et-tutorial-e,amples. 9owe.er remember that 2ic#et is a .ast and powerful tool* so you should feel confident with the topics e,posed in this document before starting to code your real applications; =or those who need further documentation on 2ic#et* there are many good boo#s a.ailable for this framewor#. 'ou can find an e,hausti.e list of these boo#s at http(//wic#et.apache.org/learn/boo#s/ 9ope youBll find this guide helpful. 9a.e fun with 2ic#et; Andrea Del Bene* an.delbene@gmail.com PS: this guide is based on Wicket 6. However if you are using an older version you should find this guide useful as well, but it's likely that the code and the snippets won't work with your version. PPS: although I've did my best working on this tutorial, this document is a work in progress and may contain errors and or omissions. !hat's why any feedback of any kind is "#$%%& appreciated'

Wicket free user guide

How to use the example code

How to use the example code


<ost of the code you will find in this document is a.ailable as a 0it repository at https(//github.com/ bitstorm/2ic#et-tutorial-e,amples and is licensed under the A"= 4.% 1. To get a local copy of the repository you can run the clone command from shell(
git clone https://github.com/bitstorm/Wicket-tutorial-examples.git

-f you arenBt used to 0it* you can simply download the whole source as a Cip archi.e(

The repository contains a multi-module <a.en proHect. I.ery subproHect is contained in the relati.e folder of the repository(

2hen the e,ample code is used in the document* you will find the name of the subproHect it belongs to. -f you donBt ha.e any e,perience with <a.en* you can read Appendi, A where you can learn the basic commands needed to wor# with the e,ample proHects and to import them into your fa.ourite -DI ( etBeans* -DIA or Iclipse).

http: www.apache.org licenses %I(#)S#*+.,

Wicket free user guide

Graphic conventions

Graphic conventions
To ma#e reading easier* some graphic con.entions ha.e been adopted(

!ode reference inside te,t are written with a different font ( FreeMono)( ...the .ariable message is....

!ode bloc#s are formatted and coloured following the default Iclipse style(
/** * This is about <code>ClassName</code>. * !link com."ourCompan".a#ackage.$nter%ace& * !author author * !deprecated use <code>'therClass</code> */ public class ClassName<(> implements $nter%aceName<)tring> enum Color

*(+, -*((N, ./0( &1

/* This comment ma" span multiple lines. */ static 'b2ect static3ield1 // This comment ma" span onl" this line pri4ate ( %ield1 // T5)6: re%actor !)uppressWarnings74alue89all9: public int %oo7$nteger parameter: abstract;ethod7:1 int local8 <=*hashCode7:1

static;ethod7:1 return bar7local: > parameter1


& &

-mportant informations and warnings are written inside bloc#s li#e these( >ote bla...bla...bla....

Warning bla...bla...bla....

Wicket free user guide

1 Why should learn Wicket!

1 Why should I learn Wicket?


"oftware de.elopment is a challenging acti.ity and de.elopers must #eep their s#ills up-to-date with new technologies. But before starting to learn the last FcoolestG framewor# we should always as# ourself if it is the right tool for us and how it can impro.e our e.eryday Hob. Ka.aBs ecosystem is already full of many well-#nown web framewor#s* so why should we spend our time learning 2ic#etJ This chapter will show you how 2ic#et is different from other web framewor#s you may #now and it will e,plain also how it can impro.e your life as web de.eloper.

1.1 We all like spaghetti :?@ ...


...but we all hate spaghetti code; ThatBs why in the first half of the 4%%%s we ha.e seen the birth of so many web framewor#s. Their mission was to separate our business code from presentation layer (li#e K"P pages). "ome of theme (li#e "truts* "pring <D!* Delocity* etc...) ha.e become widely adopted and they made the <D! pattern .ery popular among de.elopers. 9owe.er* none of these framewor#s offers a real @@ 4 abstraction for web pages and we still ha.e to ta#e care of web-related tas#s such as 9TTP reEuest/response handling* &+:s mapping* storing data into user session and so on. The biggest limit of <D! framewor#s is that they donBt do much to o.ercome the impedance mismatch between the stateless nature of 9TTP protocol and the need of our web applications of handling a (.ery comple,) state. To o.ercome these limits de.elopers ha.e started to adopt a new generation of component oriented web framewor#s designed to pro.ide a completely different approach to web de.elopment.

1.2 .omponent oriented frameworks: an overview


!omponent oriented framewor#s differ from classic web framewor#s in that they build a model of reEuested page on the ser.er side and the 9T<: sent bac# to the client is generated according to this model. 'ou can thin# of the model as if it was an FinverseG Ka.a"cript D@<* meaning that( 1. is built on server*side 4. is built before 9T<: is sent to client $. 9T<: code is generated using this model and not .ice .ersa.

llustration 1$1% General schema of page re&uest handling for a component oriented framework
2 "b#ect "riented

Wicket free user guide

1 Why should learn Wicket!

2ith this #ind of framewor# our web pages and their 9T<: components (forms* input controls* lin#s* etc...)* are pure class instances. "ince pages are class instances they li.e inside the KD< heap and we can handle them as we do with any other Ka.a class. This approach is .ery similar to what 0&- framewor#s (li#e "wing or "2T) do with des#top windows and their components. 2ic#et and the other component oriented framewor#s bring to web de.elopment the same #ind of abstraction that 0&- framewor#s offer when we build a des#top application. <ost of those #ind of framewor#s hide the details of the 9TTP protocol and naturally sol.e the problem of its stateless nature.

1.3 ;enefits of component oriented frameworks for we= development


At this point some people may still wonder why @@P is so important also for web de.elopment and what benefits it can bring to de.elopers. :etBs Euic#ly re.iew the main ad.antages that this paradigm can offer us(

We= pages are o=<ects( web pages are not Hust te,t files sent bac# to the client. They are obHect instances and we can harness @@P to design web pages and their components. 2ith 2ic#et we can also apply inheritance to 9T<: mar#up in order to build a consistent graphic layout for our applications (we will see markup inheritance in chapter $). We donAt have to worr a=out applicationAs state ( pages and components can be considered stateful entities. They are Ka.a obHects and they can #eep a state inside them and reference other obHects. 2e can stop worrying about #eeping trac# of user data stored inside the HttpSession and we can start managing them in a natural and transparent way. *esting we= applications is much easier ( since pages and components are pure obHects* you can use K&nit to test their beha.ior and to ensure that they render as e,pected. 2ic#et has a set of utility classes for unit testing that simulate user interaction with web pages* hence we can write acceptance tests using Hust K&nit without any other test framewor# (unit testing is co.ered in chapter 18).

1.# Wicket vs the other component oriented frameworks


2ic#et is not the only component oriented framewor# a.ailable in the Ka.a ecosystem. Among its competitors we can find 02T (from 0oogle)* K"= (from @racle)* Daadin (from Daadin :td.)* etc... I.en if 2ic#et and all those other framewor#s ha.e their pros and cons* there are good reasons to prefer 2ic#et o.er them(

Wicket is 1//B open source: 2ic#et is a top Apache proHect and it doesnBt depend on any pri.ate company. 'ou donBt ha.e to worry about future licensing changes* 2ic#et will always be released under Apache license 4.% and freely a.ailable. Wicket is a communit driven pro<ect: The 2ic#et team supports and promotes the dialogue with the framewor#Bs users through two mailing lists (one for users and another one for framewor# de.elopers)$ and an Apache K-+A3 (the issue trac#ing system). <oreo.er* as any other Apache proHect* 2ic#et is de.eloped paying great attention to user feedbac#s and to suggested features.

3 4

'ee http: wicket.apache.org help email.html https: issues.apache.org -ira browse .I(/#!

Wicket free user guide

1 Why should learn Wicket!

Wicket is <ust a=out 7ava and good old H*+,: almost all web framewor#s force users to adopt special tags or to use ser.er side code inside 9T<: mar#up. This is clearly in contrast with the concept of separation between presentation and business logic and it leads to a more confusing code in our pages. -n 2ic#et we donBt ha.e to ta#e care of generating 9T<: inside the page itself* and we wonBt need to use any tag other than standard 9T<: tags. All we ha.e to do is to attach our components (Ka.a instances) to the 9T<: tags using a simple tag attribute called wicket:id (we will shortly see how to use it). With Wicket we can easil use 7ava;eans and PC7C ( in our we= tire: one of the most annoying and error-prone tas# in web de.elopment is collecting user input through a form and #eeping form fields updated with pre.iously inserted .alues. This usually reEuires a huge amount of code to e,tract input from reEuest parameters (which are strings)* parse them to Ka.a types and store them into some #ind of .ariable. And this is Hust half of the wor# we ha.e to do as we must implement the in.erse path (load data from Ka.a to the web form). <oreo.er* most of the times our forms will use a Ka.aBean or a P@K@ as bac#ing obHect* meaning that we must manually map form fields with the corresponding obHect fields and .ice .ersa. 2ic#et comes with an intuiti.e and fle,ible mechanism that does this mapping for us without any configuration o.erhead (using a convention over configuration approach) and in a transparent way. !hapter 8 will introduce the concept of 2ic#et model and we will learn how to harness this entity with forms. >o complex 9+, needed: 2ic#et was designed to minimiCe the amount of configuration files needed to run our applications. o L<: file is reEuired e,cept for the standard deployment descriptor web.0ml.

(or a definition of P")" see http: en.wikipedia.org wiki Plain12ld13ava12b-ect

Wicket free user guide

* Wicket says +Hello world,-

Wicket says Hello world!


2ic#et allows us to design our web pages in terms of components and containers* Hust li#e A2T does with des#top windows. Both framewor#s share the same component-based architecture( in A2T we ha.e a Windows instance which represents the physical windows containing 0&- components (li#e te,t fields* radio buttons* drawing areas* etc...)* in 2ic#et we ha.e a WebPage instance which represents the physical web page containing 9T<: components (pictures* buttons* forms* etc... ) .

-n both framewor#s we find a base class for 0&- components called Component. 2ic#et pages can be composed (and usually are) by many components* Hust li#e A2T windows are composed by "wing/A2T components. Both framewor#s promote the reuse of presentation code and 0&- elements building custom components. I.en if 2ic#et already comes with a rich set of ready-to-use components* building custom components is a common practice when wor#ing with this framewor#. 2eBll learn more about custom components in the ne,t chapters.

2.1 Wicket distri=ution and modules


2ic#et is a.ailable as a binary pac#age on the main site http(//wic#et.apache.org. -nside this archi.e we can find the distribution Hars of the framewor#. Iach Har corresponds to a sub-module of the framewor#. The following table reports these modules along with a short description of their purpose and with the related dependencies(

+oduleAsname
wic#et-core wic#et-reEuest wic#et-util

5escription

5ependencies

!ontains the main classes of the framewor#* li#e - wic#et-reEuest class Component and Application. - wic#et-util This module contains the classes in.ol.ed into web - wic#et-util reEuest processing. !ontains general-purpose utility functional areas such as -/@* manipulation* security* etc... classes for lang* string one.

Wicket free user guide

* Wicket says +Hello world,-

wic#et-datetime wic#et-de.utils

!ontains special purpose components designed to -wic#et-core wor# with date and time. !ontains utility classes and components to help -wic#et-core de.elopers with tas#s such as debugging* class -wic#et-e,tensions inspection and so on. !ontains a .ast set of built-in components to build -wic#et-core a rich &- for our web application (AHa, support is part of this module). Pro.ides support for role-based authoriCation. -wic#et-core

wic#et-e,tensions

wic#et-auth-roles wic#et-ioc

This module pro.ides common classes to support -wic#et-core -n.ersion @f !ontrol. -tBs used by both "pring and 0uice integration module. This module pro.ides integration with the -wic#et-core dependency inHection framewor# de.eloped by -wic#et-ioc 0oogle. This module pro.ides integration with "pring -wic#et-core framewor#. -wic#et-ioc This module pro.ides panels and utility class to -wic#et-core integrate 2ic#et with Delocity template engine. This module pro.ides panels and utility class to -wic#et-core integrate 2ic#et with 3ava 4anagement #0tensions. Pro.ides integration with Ka.a agent libraries and -wic#et-core instrumentation tools.

wic#et-guice

wic#et-spring wic#et-.elocity wic#et-Hm,

wic#et-obHectsiCeof-agent

Please note that the core module depends on the utility and re5uest modules* hence it cannot be used without them.

2.2 .onfiguration of Wicket applications


-n this chapter we will see a classic Hello .orld' e,ample implemented using a 2ic#et page with a built-in component called Label (the code is from proHect the Hello.orld#0ample) "ince this is the first e,ample of the guide* before loo#ing at Ka.a code we will go through the common artifacts needed to build a 2ic#et application from scratch. >ote All the e,ample proHects presented in this document ha.e been generated using <a.en and the utility page at http(//wic#et.apache.org/start/Euic#start.html. Appendi, A contains the instructions needed to use these proHects and build a Euic#start application using Apache <a.en. All the artifacts used in the ne,t e,ample (files web.,ml* 9omePage.class and 9omePage.html) are automatically generated by <a.en.

2.2.1

Wicket application structure

A 2ic#et application is a standard Ka.a II web application* hence it is deployed through a web.0ml file placed inside folder 2IB-- =A(

'ee +.irectory 'tructure- paragraph of 'ervlet 'pecification document

Wicket free user guide

* Wicket says +Hello world,-

llustration *$1% The standard directory structure of a Wicket application The content of web.,ml declares a ser.let filter (class org.apache.wicket.Protocol.http. WicketFilter) which dispatches web reEuests to our 2ic#et application(
<?xml 4ersion89@.A9 encoding890T3-B9?> <Ceb-app> <displa"-name>Wicket Test</displa"-name> <%ilter> <%ilter-name>Test5pplication</%ilter-name> <%ilter-class>org.apache.Cicket.protocol.http.Wicket3ilter</%ilter-class> <init-param> <param-name>applicationClassName</param-name> <param-4alue>org.CicketTutorial.Wicket5pplication</param-4alue> </init-param> </%ilter> <%ilter-mapping> <%ilter-name>Test5pplication</%ilter-name> <url-pattern>/*</url-pattern> </%ilter-mapping> </Ceb-app>

mapping>

"ince this is a standard ser.let filter we must map it to a specific set of &+:s through the tag). -n the ,ml abo.e we ha.e mapped e.ery &+: to our 2ic#et filter. >ote

<%ilter-

2ic#et can be started in two modes named respecti.ely 5DED,CP+D>* and 5DP,CF+D>*. The first mode acti.ates some e,tra features which help application de.elopment* li#e resources monitoring and reloading* full stac# trace rendering of e,ceptions* an AKAL debugger window* etc... The DIP:@'<I T mode turns off all these features optimiCing performances and resource consumption. -n our e,ample proHects we will use the default mode which is DIDI:@P<I T. Appnedi, A contains the chapter F"witching 2ic#et to DIP:@'<I T modeF where we can find further details about these two modes as well as the possible ways we ha.e to set the desired one. -n any case* 5C >C* deploy your applications in a production en.ironment without switching to DIP:@'<I T mode;

2.2.2

*he application class

-f we loo# bac# at web.0ml we can see that we ha.e pro.ided the 2ic#et filter with a parameter called applicationClassName. This .alue must be the fully Eualified class name of a subclass of org.
Wicket free user guide

* Wicket says +Hello world,-

apache.wicket.Application. This subclass represents our web application built upon 2ic#et and itBs responsible for configuring it when the ser.er is starting up. <ost of the times our custom application class wonBt inherit directly from class Application* but rather from class org.apache.wicket .protocol.http.WebApplication which pro.ides a closer integration with ser.let infrastructure. !lass Application comes with a set of configuration methods that we can o.erride to customiCe our applicationBs settings. @ne of these methods is getHomePage( that must be o.erridden as it is declared abstract(
public abstract Class<? extends #age> getDome#age7:

As you may guess from its name* this method specifies which page to use as homepage for our application. Another important method is init( (
protected 4oid init7:

This method is called when our application is loaded by the web ser.er (Tomcat* Ketty* etc...) and is the ideal place to put our configuration code. The Application class e,poses its settings grouping them into interfaces (you can find them in pac#age org.apache.wicket.settings). 2e can access these interfaces through getter methods that will be gradually introduced in the ne,t chapters when we will co.er the related settings. The current applicationBs instance can be retrie.ed at any time calling static method Application.get( in our code. 2e will gi.e more details about this method in paragraph 6.$. The content of the application class from proHect Hello.orld#0ample is the following(
public class Wicket5pplication extends Web5pplication !'4erride public Class<? extends Web#age> getDome#age7: return Dome#age.class1 & !'4erride public 4oid init7: super.init7:1 // add "our con%iguration here & &

"ince this is a .ery basic e,ample of a 2ic#et application* we donBt need to specify anything inside the init method. The home page of the application is the HomePage class. -n the ne,t paragraph we will see how this page is implemented and which con.entions we ha.e to follow to create a page in 2ic#et. >ote Declaring a WicketFilter inside web.0ml descriptor is not the only way we ha.e to #ic#start our application. -f we prefer to use a ser.let instead of a filter* we can use class org.apache.

Wicket free user guide

1%

* Wicket says +Hello world,-

wicket.protocol.http.WicketSer!let. "ee the Ka.aDoc for further details.

2.3 *he HomePage class


To complete our first 2ic#et application we must e,plore the home page class that is returned by the ApplicationBs method getHomePage( seen abo.e. -n 2ic#et a web page is a subclass of org.apache.wicket.WebPage. This subclass must ha.e a corresponding 9T<: file which will be used by the framewor# as template to generate its 9T<: mar#up. This file is a regular plain 9T<: file (its e,tension must be html). By default this 9T<: file must ha.e the same name of the related page class and must be in the same pac#age(

llustration *$*%Page class and its related HT/0 file -f you donBt li#e to put class and html side by side (letBs say you want all your 9T<: files in a separated folder) you can use 2ic#et settings to specify where 9T<: files can be found. 2e will co.er this topic later in paragraph 1$.8. The Ka.a code for the HomePage class is the following(
package org.CicketTutorial1 import org.apache.Cicket.reEuest.mapper.parameter.#age#arameters1 import org.apache.Cicket.markup.html.basic./abel1 import org.apache.Cicket.markup.html.Web#age1 public class Dome#age extends Web#age public Dome#age7: add7neC /abel79hello;essage9, 9Dello WicketWorldF9::1 & &

Apart from subclassing WebPage* HomePage defines a constructor that adds a Label component to itself. <ethod add(Component component is inherited from ancestor class org.apache.wicket. Mark"pContainer and is used to add children components to a web page. 2eBll see more about Mark"pContainer later in chapter $.4.4. !lass org.apache.wicket.mark"p.html.basic.Label is the simplest component shipped with 2ic#et. -t Hust inserts a string (the second argument of its constructor) inside the corresponding 9T<: tag. Kust li#e any other 2ic#et component* Label needs a te,tual id (#helloMessage# in our e,ample) to be instantiated. At runtime 2ic#et will use this .alue to find the 9T<: tag we want to bind to the component. This tag must ha.e a special attribute called Cicket:id and its .alue must be identical to the component id (comparison is case-sensiti.e;). 9ere is the 9T<: mar#up for HomePage (file 9omePage.html)(
Wicket free user guide

11

* Wicket says +Hello world,-

<F+'CTG#( html> <html> <head> <meta charset89ut%-B9 /> <title>5pache Wicket DelloWorld</title> </head> <bod"> <di4 Cicket:id89hello;essage9> H/abelIs message goes hereJ </di4> </bod"> </html>

2e can see that the Cicket:id attribute is set according to the .alue of the component id. -f we run this e,ample we will see the te,t Hello WicketWorld$ -nside a <di4> tag. >ote Label replaces the original content of its tag (in our e,ample %Label#s message goes here&) with the string passed as .alue ( Hello WicketWorld$ in our e,ample). Warning -f we specify a Cicket:id attribute for a tag without adding the corresponding component in our Ka.a code* 2ic#et will throw a ComponentNotFo"nd '(ception. @n the contrary if we add a component in our Ka.a code without specifying a corresponding Cicket:id attribute in our mar#up* 2ic#et will throw a Wicket)"ntime'(ception.

2.# Wicket ,inks


The basic form of interaction offered by web applications is to na.igate through pages using lin#s. -n 9T<: a lin# is basically a pointer to another resource that most of the time is another page. 2ic#et implements lin#s with component org.apache.wicket.mark"p.html.link.Link* but due to the component-oriented nature of the framewor#* this component is Euite different from classic 9T<: lin#s. =ollowing the analogy with 0&- framewor#s* we can consider 2ic#et lin# as a Fclic#G e.ent handler( its purpose is to perform some actions (on ser.er side;) when the user clic#s on it. That said* you shouldnBt be surprised to find an abstract method called onClick( inside the Link class. -n the following e,ample we ha.e a page with a Link containing an empty implementation of onClick(
public class Dome#age extends Web#age public Dome#age7: add7neC /ink79id9: !'4erride public 4oid onClick7:

Wicket free user guide

14

* Wicket says +Hello world,-

//link code goes here & &:1 & &

By default after onClick has been e,ecuted* 2ic#et will send bac# to the current page to the client web browser. -f we want to na.igate to another page we must use method set)esponsePage of class Component(
public class Dome#age extends Web#age public Dome#age7: add7neC /ink79id9: !'4erride public 4oid onClick7: //Ce redirect broCser to another page. set*esponse#age75nother#age.class:1 & &:1 & &

-n the e,ample abo.e we used a .ersion of set)esponsePage which ta#es as input the class of the target page. -n this way a new instance of AnotherPage will be create each time we clic# on the lin#. The other .ersion of set)esponsePage ta#es in input a page instance instead of a page class(
//... !'4erride public 4oid onClick7: //Ce redirect broCser to another page. 5nother#age another#age 8 neC 5nother#age7:1 set*esponse#age7another#age:1 & //...

The difference between using the first .ersion of set)esponsePage rather than the second one will be illustrated in chapter A* when we will introduce the topic of stateful and stateless pages. =or now* we can consider them as eEui.alent. >ote 2ic#et comes with a rich set of lin# components suited for e.ery need (lin#s to static &+:* AHa,-enhanced lin#s* lin#s to a file to download* lin#s to e,ternal pages and so on). 2e will see them in chapter 7.

2.( 8ummar
-n this chapter we ha.e seen the basic elements that compose a 2ic#et application. 2e ha.e started preparing the configuration artifacts needed for our applications. As promised in paragraph 1.3* we needed to put in place Hust a minimal amount of L<: with an application class and a home page.

Wicket free user guide

1$

* Wicket says +Hello world,-

Then we ha.e continued our Ffirst contactG with 2ic#et learning how to build a simple page with a label component as child. This e,ample page has shown us how 2ic#et maps components to 9T<: tags and how it uses both of them to generate the final 9T<: mar#up. -n the last paragraph we had a first taste of 2ic#et lin#s and we ha.e seen how they can be considered as a Fclic#G e.ent listener and how they can be used to na.igate from a page to another.

Wicket free user guide

13

1 Wicket as page layout manager

! Wicket as page layout manager


Before going ahead with more ad.anced topics* we will see how to maintain a consistent layout across our site using 2ic#et and its component-oriented features. Probably this is not the most interesting use we can get out of 2ic#et* but it is surely the simplest one so itBs the best way to get our hands dirty with some code.

3.1 HeaderG footerG left menuG contentG etc...


There was a time in the 8%s when -nternet was Hust a buCCword and watching a plain 9T<: page being rendered by a browser was a new and amaCing e,perience. -n those days we used to organiCe our page layout using the <%rame> 9T<: tag. @.er the years this tag has almost disappeared from our code and it sur.i.es only in few specific domains. =or e,ample is still being used by Ka.aDoc(

llustration 1$1% The new look of )ava.oc 2 2ith the adoption of ser.er side technologies li#e K"P* A"P or P9P the tag <%rame> has been replaced by a template-based approach where we di.ide our page layout into some common areas that will be present in each page of our web application. Then* we manually insert these areas in e.ery page including the appropriate mar#up fragments. -n this chapter we will see how to use 2ic#et to build a site layout. The sample layout we will use is a typical page layout consisting of the following areas( a header which could contain site title* some logos* a na.igation bar* etc... a left menu with a bunch of lin#s to different areas/functionalities of the site. a footer with generic informations li#e web masterBs email* the company address* etc...
Wicket free user guide

15

1 Wicket as page layout manager

a content area which usually contains the functional part of the page.

The following picture summarises the layout structure(

llustration 1$*% 7n abstract view of layout areas @nce we ha.e chosen a page layout* our web designer can start building up the site theme. The result is a beautiful moc# of our future web pages. @.er this moc# we can map the original layout areas 6(

llustration 1$1% 0ayout areas over the theme mock


7 The mock is taken from charity pro#ect )ug3Tenda 4http: -ava.net pro-ects -ugancona56 lead by talian )ug /arche$

Wicket free user guide

1A

1 Wicket as page layout manager

ow in order to ha.e a consistent layout across all the site* we must ensure that each page will include the layout areas seen abo.e. 2ith an old template-based approach we must manually put them inside e.ery page. -f we were using K"P we would probably end up using incl"de directi.e to add layout areas in our pages. 2e would ha.e one incl"de for each of the areas (e,cept for the content)(

llustration 1$3% 0ayout areas are assembled with include directive >ote =or the sa#e of simplicity we can consider each included area as a static 9T<: fragment. ow letBs see how we can handle the layout of our web application using 2ic#et.

3.2 Here comes the inheritance%


The need of ensuring a consistent layout across our pages un.eiled a serious limit of the 9T<:( the inability to apply inheritance to web pages and their mar#up. 2ouldnBt be great if we could write our layout once in a page and then inherit it in the other pages of our applicationJ @ne of the goals of 2ic#et is to o.ercome this #ind of limit.

3.2.1

+arkup inheritance

As we ha.e seen in the pre.ious chapter* 2ic#et pages are pure Ka.a classes* so we can easily write a page which is a subclass of another parent page. But in 2ic#et inheritance is not limited to the classic obHect-oriented code inheritance. 2hen a class subclasses a WebPage it also inherits the 9T<: file of to the parent class. This type of inheritance is called markup inheritance. To better illustrate this concept letBs consider the following e,ample where we ha.e a page class called *enericSitePage with the corresponding 9T<: file *enericSitePage.html. ow letBs create a specific page called +rderCheck+"tPage where users can chec# out their orders on our our web site.

Wicket free user guide

16

1 Wicket as page layout manager

This class e,tends *enericSitePage but we donBt pro.ide it with any corresponding 9T<: file. -n this scenario +rderCheck+"tPage will use *enericSitePage.html as mar#up file(

llustration 1$9% Page "rderCheck"utPage hasn:t a corresponding HT/0 file$ t will use the one from parent page 4General'itePage$html5$ <ar#up inheritance comes in handy for page layout management as it helps us a.oid the burden of chec#ing that each page conforms to the site layout. 9owe.er to fully ta#e ad.antage of mar#up inheritance we must first learn how to use another important component of the framewor# that supports this feature( the panel. Warning -f no mar#up is found (nor directly assigned to the class* neither inherited from an ancestor) a Mark"pNotFo"nd'(ception is thrown.

3.2.2

Panel class

!lass org.apache.wicket.mark"p.html.panel.Panel is a special component which lets us reuse 0&- code and 9T<: mar#up across different pages and different web applications. -t shares a common ancestor class with WebPage class* which is org.apache.wicket.Mark"pContainer(

llustration 1$8% Hierarchy of WebPage and Panel classes

Wicket free user guide

17

1 Wicket as page layout manager

"ubclasses of Mark"pContainer can contain children components that can be added with method add(Componet... (seen in chapter 4.$). Mark"pContainer implements a full set of methods to manage children components. The basic operations we can do on them are( add one or more children components (with method add). remo.e a specific child component (with methods remo!e). retrie.e a specific child component with method get(String . The string parameter is the id of the component or its relati.e path if the component is nested inside other Mark"pContainers. This path is a colon-separated string containing also the ids of the intermediate containers tra.ersed to get to the child component. To illustrate an e,ample of component path* letBs consider the code of the following page(
;"#anel m"#anel 8 neC ;"#anel 79innerContainer9:1 add7m"#anel:1

!omponent M,Panel is a custom panel containing only a label ha.ing 9name9 as id. &nder those conditions we could retrie.e this label from the container page using the following path e,pression(
/abel name 8 7/abel:get79innerContainer:name9:1

replace a specific child component with a new component having the same id (with method replace). iterate thought children components with the iterator returned by method iterator or using .isitor pattern7 with methods !isitChildren.

Both Panel and WebPage ha.e their own associated mar#up file which is used to render the corresponding component. -f such file is not pro.ided* 2ic#et will apply markup inheritance loo#ing for a mar#up file through their ancestor classes. 2hen a panel is attached to a container* the content of its mar#up file is inserted into its related tag. 2hile panels and pages ha.e much in common* there are some notable differences between these two components that we should #eep in mind. The main difference between them is that pages can be rendered as standalone entities while panels must be placed inside a page to be rendered. Another important difference is the content of their mar#up file( for both WebPage and Panel this is a standard 9T<: file* but Panel uses a special tag to indicate which part of the whole file will be considered as mar#up source. This tag is <Cicket:panel>. A mar#up file for a panel will typically loo# li#e this(
<html> <head> <meta http-eEui489Content-T"pe9 content89text/html1 charset80T3-B9> ... </head> <bod"> <Cicket:panel> <F-- Gour markup goes here --> </Cicket:panel> </bod">

The 9T<: outside tag


8

<Cicket:panel>

will be remo.ed during rendering phase. The space outside this

http: en.wikipedia.org wiki 6isitor1pattern

Wicket free user guide

18

1 Wicket as page layout manager

tag can be used by both web de.elopers and web designers to place some moc# 9T<: to show how the final panel should loo# li#e.

3.3 5ivide et impera%


:etBs go bac# to our layout e,ample. -n chapter $.1 we ha.e di.ided our layout in common areas that must be part of e.ery page. ow we will build a reusable template page for our web application combining pages and panels. The code e,amples are from proHect 4arkupInheritance#0ample.

3.3.1

Panels and la out areas

=irst* letBs build a custom panel for each layout area (e,cept for BcontentB area). =or e,ample gi.en the header area

we can build a panel called HeaderPanel with a related mar#up file called HeaderPanel.html containing the 9T<: for this area(
<html> <head> <meta http-eEui489Content-T"pe9 content89text/html1 charset80T3-B9> ... </head> <bod"> <Cicket:panel> <table Cidth89@AAK9 st"le89border: Apx none19> <tbod"> <tr> <td> <img alt89Lug<Tenda9 src89Cicket/a"outM%iles/logoM2ug<tenda.gi%9> </td> <td> <h@>-estione 5nagra%ica</h@> </td> </tr> </tbod"> </table> </Cicket:panel> </bod"> <html>

The class for this panel simply e,tends base class Panel(
package helloWorld.la"outTenda1 import org.apache.Cicket.markup.html.panel.#anel1 public class Deader#anel extends #anel public Deader#anel7)tring id: super7id:1 & &

=or each layout area we will build a panel li#e the one abo.e that holds the appropriate 9T<: mar#up. -n the end we will ha.e the following set of panels( HeaderPanel

Wicket free user guide

4%

1 Wicket as page layout manager

HooterPanel +enuPanel

!ontent area will change from page to page* so we donBt need a reusable panel for it.

3.3.2

*emplate page

ow we can build a generic template page using our brand new panels. -ts mar#up is Euite straightforward (
<html> <head> <meta http-eEui489Content-T"pe9 content89text/html1 charset80T3-B9> ... <F--$nclude C))--> ... </head> <bod"> <di4 id89header9 Cicket:id89header#anel9>header</di4> <di4 id89bod"9> <di4 id89menu9 Cicket:id89menu#anel9>menu</di4> <di4 id89content9 Cicket:id89content9>content</di4> </di4> <di4 id89%ooter9 Cicket:id89%ooter#anel9>%ooter</di4> </bod"> </html>

<di4>

The 9T<: code for this page implements the generic left-menu layout of our site. 'ou can note the 3 tags used as containers for the corresponding areas. The page class contains the code to physically assemble the page and panels(
package helloWorld.la"outTenda1 import org.apache.Cicket.markup.html.Web#age1 public class LugTemplate extends Web#age public static %inal )tring C'NT(NTM$+ 8 9contentComponent91 pri4ate Component header#anel1 pri4ate Component menu#anel1 pri4ate Component %ooter#anel1 public LugTemplate7: add7header#anel 8 neC Deader#anel79header#anel9::1 add7menu#anel 8 neC ;enu#anel79menu#anel9::1 add7%ooter#anel 8 neC 3ooter#anel79%ooter#anel9::1 add7neC /abel7C'NT(NTM$+, 9#ut "our content here9::1 & //getters %or la"out areas //... &

Done; @ur template page is ready to be used. ow all the pages of our site will be subclasses of this parent page and they will inherit the layout and the 9T<: mar#up. They will only substitute the Label inserted as content area with their custom content.

3.3.3

Hinal example

As final e,ample we will build the login page for our site. 2e will call it SimpleLoginPage. =irst* we
Wicket free user guide

41

1 Wicket as page layout manager

need a panel containing the login form. This will be the content area of our page. 2e will call it LoginFormPanel and the mar#up is the following(
<html> <head> ... </head> <bod"> <Cicket:panel> <di4 st"le89margin: auto1 Cidth: <AK19> <%orm id89login3orm9 method89get9> <%ieldset id89login9 class89center9> <legend >/ogin</legend> <span >0sername: </span><input t"pe89text9 id89usernameN/><br/> <span >#assCord: </span><input t"pe89passCord9 id89passCord9 /> <p> <input t"pe89submit9 name89login9 4alue89login9/> </p> </%ieldset> </%orm> </di4> </Cicket:panel> </bod"> </html>

The class for this panel Hust e,tends Panel class so we wonBt see the relati.e code. The form of this panel is for illustrati.e purpose only. 2e will see how to wor# with 2ic#et forms in chapters 8 and 1%. "ince this is a login page we donBt want it to display the left menu area. ThatBs not a big deal as Component class e,poses a method called set-isible which sets whether the component and its children should be displayed. The resulting Ka.a code for the login page is the following(
package helloWorld.la"outTenda1 import helloWorld./ogin#anel1 import org.apache.Cicket.e4ent..roadcast1 import org.apache.Cicket.e4ent.$(4ent)ink1 public class )imple/ogin#age extends LugTemplate public )imple/ogin#age7: super7:1 replace7neC /ogin#anel7C'NT(NTM$+::1 get;enu#anel7:.setOisible7%alse:1 & &

@b.iously this page doesnBt come with a related mar#up file. 'ou can see the final page in the following picture(

Wicket free user guide

44

1 Wicket as page layout manager

llustration 1$2% (inal login page

3.# +arkup inheritance with the <Cicket:extend> tag


2ith 2ic#et we can apply mar#up inheritance using another approach based on the tag This tag is used inside the parentBs mar#up to define where the children pages/panels can FinHectG their custom mar#up e,tending the mar#up inherited from the parent component. An e,ample of a parent page using the tag <Cicket:child> is the following(
<Cicket:child>. <html> <head> <meta http-eEui489Content-T"pe9 content89text/html1 charset80T3-B9> ... </head> <bod"> This is parent bod"F <Cicket:child/> </bod"> </html>

The mar#up of a child page/panel must be placed inside the tag <Cicket:extend>. @nly the mar#up inside <Cicket:extend> will be included in final mar#up. 9ere is an e,ample of child page mar#up(
<html> <head> <meta http-eEui489Content-T"pe9 content89text/html1 charset80T3-B9> ... </head> <bod"> <Cicket:extend> This is child bod"F </Cicket:extend> </bod"> </html>

!onsidering the two pages seen abo.e* the final mar#up generated for child page will be the following(
<html> <head> <meta http-eEui489Content-T"pe9 content89text/html1 charset80T3-B9> ... </head> <bod">

Wicket free user guide

4$

1 Wicket as page layout manager

This is parent bod"F <Cicket:child> <Cicket:extend> This is child bod"F </Cicket:extend> </Cicket:child> </bod"> </html>

3.#.1

Cur example revisited

Applying <Cicket:child> tag to our layout e,ample* we obtain the following mar#up for the main template page(
<html> <head> <meta http-eEui489Content-T"pe9 content89text/html1 charset80T3-B9> ... </head> <bod"> <di4 id89header9 Cicket:id89header#anel9>header</di4> <di4 id89bod"9> <di4 id89menu9 Cicket:id89menu#anel9>menu</di4> <Cicket:child/> </di4> <di4 id89%ooter9 Cicket:id89%ooter#anel9>%ooter</di4> </bod"> </html>

2e ha.e replaced the <di4> tag of the content area with the tag <Cicket:child>. 0oing forward with our e,ample we can build a login page creating class SimpleLoginPage which e,tends the ."g/emplate page* but with a related mar#up file li#e this(
<html> <head> ... </head> <bod"> <Cicket:extend> <di4 st"le89margin: auto1 Cidth: <AK19> <%orm id89login3orm9 method89get9> <%ieldset id89login9 class89center9> <legend >/ogin</legend> <span >0sername: </span><input t"pe89text9 id89usernameN/><br/> <span >#assCord: </span><input t"pe89passCord9 id89passCord9 /> <p> <input t"pe89submit9 name89login9 4alue89login9/> </p> </%ieldset> </%orm> </di4> </Cicket:extend> </bod"> </html>

As we can see this approach doesnBt reEuire to create custom panels to use as content area and it can

Wicket free user guide

43

1 Wicket as page layout manager

be useful if we donBt ha.e to handle a 0&- with a high degree of comple,ity.

3.( 8ummar
2ic#et applies inheritance also to 9T<: mar#up ma#ing layout management much easier and less error-prone. Defining a master template page to use as base class for the other pages is a great way to build a consistent layout and use it across all the pages on the web site. During the chapter we ha.e also introduced the Panel component* a .ery important 2ic#et class that is primarily designed to let us di.ide our pages in smaller and reusable &- components.

Wicket free user guide

45

3 ;eeping control over HT/0

" #eeping control over H$%L


<any 2ic#et newbies are initially scared by its approach to web de.elopment because they ha.e the impression that the component-oriented nature of the framewor# pre.ents them from ha.ing direct control o.er the generated mar#up. This is due to the fact that many de.elopers come from other ser.erside technologies li#e K"P where we physically implement the logic that controls how the final 9T<: is generated. This chapter will pre.ent you from ha.ing any initial misleading feeling about 2ic#et showing you how to control and manipulate the generated 9T<: with the built-in tools shipped with the framewor#.

#.1 Hiding or disa=ling a component


At the end of the pre.ious chapter we ha.e seen how to hide a component calling its method set-isible. -n a similar fashion* we can also decide to disable a component using method set'nabled. 2hen a component is disabled all the lin#s inside it will be in turn disabled (they will be rendered as <span>)8 and it can not fire Ka.a"cript e.ents. !lass Component pro.ides two getter methods to determinate if a component is .isible or enabled( is-isible and is'nabled. I.en if nothing pre.ents us from o.erriding these two methods to implement a custom logic to determinate the state of a component* we should #eep in mind that methods is-isible and is'nabled are called multiple times before a component is fully rendered. 9ence* if we place nontri.ial code inside these two methods* we can sensibly deteriorate the responsi.eness of our pages. As we will see in the ne,t chapter* class Component pro.ides method onCon0ig"re which is more suited to contain code that contributes to determinate component states because it is called Hust once during rendering phase.

#.2 +odifing tag attri=utes


To modify tag attributes we can use class org.apache.wicket.Attrib"teModi0ier. This class e,tends org.apache.wicket.beha!ior.1eha!ior and can be added to any component .ia the ComponentBs add method. !lass 1eha!ior is used to e,pand component functionalities and it can also modify component mar#up. 2e will see this class in detail later in paragraph 15.1. As first e,ample of attribute manipulation letBs consider a Label component bound to the following mar#up(
<span Cicket:id89simple/abel9></span>

"uppose we want to add some style to label content ma#ing it red and bolded. 2e can add to the label an Attrib"teModi0ier which creates the tag attribute st"le with .alue 9color:red1%ontCeight:bold9(
label.add7neC 5ttribute;odi%ier79st"le9, 9color:red1%ont-Ceight:bold9::1

-f attribute st"le already e,ists in the original mar#up* it will be replaced with the .alue specified by Attrib"teModi0ier. -f we donBt want to o.erwrite the e,isting .alue of an attribute we can use
9 The markup used to render disabled links can be customi<ed as described at the end of paragraph =$1

Wicket free user guide

4A

3 ;eeping control over HT/0

subclass Attrib"teAppender which will append its .alue to the e,isting one(
label.add7neC 5ttribute5ppender79st"le9, 9color:red1%ont-Ceight:bold9::1

2e can also create attribute modifiers using factory methods pro.ided by class Attrib"teModi0ier and itBs also possible to prepend a gi.en .alue to an e,isting attribute(
// replaces existing 4alue Cith the gi4en one label.add75ttribute;odi%ier.replace79st"le9, 9color:red1%ont-Ceight:bold9::1

//appends the gi4en 4alue to the existing one label.add75ttribute;odi%ier.append79st"le9, 9color:red1%ont-Ceight:bold9::1

//prepends the gi4en 4alue to the existing one label.add75ttribute;odi%ier.prepend79st"le9, 9color:red1%ont-Ceight:bold9::1

#.3 Generating tag attri=ute AidA


Tag attribute id plays a crucial role in web de.elopment as it allows Ka.a"cript to identify a D@< element. ThatBs why class Component pro.ides two dedicated methods to set this attribute. 2ith method set+"tp"tMark"p2d(boolean o"tp"t we can decide if the id attribute will be rendered or not in the final mar#up (by default is not rendered). The .alue of this attribute will be automatically generated by 2ic#et and it will be uniEue for the entire page. -f we need to specify this .alue by hand* we can use method setMark"p2d(String id . The .alue of the id can be retrie.ed with method getMark"p2d( .

#.# .reating in?line panels with We=+arkup.ontainer


!reate custom panels is a great way to handle comple, user interfaces. 9owe.er* sometimes we may need to create a panel which is used only by a specific page and only for a specific tas#. -n situations li#e these component org.apache.wicket.mark"p.html.WebMark"pContainer is better suited than custom panels because it can be directly attached to a tag in the parent mar#up without needing a corresponding html file (hence it is less reusable). :etBs consider for e,ample the main page of a mail ser.ice where users can see a list of recei.ed mails. "uppose that this page shows a notification bo, where user can see if new messages ha.e arri.ed. This bo, must be hidden if there are no messages to display and it would be nice if we could handle it as if it was a 2ic#et component. "uppose also that this information bo, is a <di4> tag li#e this inside the page(
<di4 Cicket:id89in%ormation.ox9> //hereIs the bod" ... GouI4e got <span Cicket:id89messagesNumber9></span> neC messages. ... </di4>

&nder those conditions we can consider using a WebMark"pContainer component rather than implementing a new panel. The code needed to handle the information bo, inside the page could be the following(

Wicket free user guide

46

3 ;eeping control over HT/0

//#age initialiPation code ... Web;arkupContainer in%ormation.ox 8 neC Web;arkupContainer 79in%ormation.ox9:1 in%ormation.ox.add7neC /abel79messagesNumber9, messagesNumber::1 add7in%ormation.ox:1 ... //$% there are no neC messages, hide in%ormation.ox in%ormation.ox.setOisible7%alse:1

As you can see in the snippet abo.e we can handle our information bo, from Ka.a code as we do with any other 2ic#et component.

#.( Working with markup fragments


Another circumstance in which we may prefer to a.oid the creation of custom panels is when we want to conditionally display in a page small fragments of mar#up. -n this case if we decided to use panels* we would end up ha.ing a huge number of small panel classes with their related mar#up file. To better cope with situations li#e this* 2ic#et defines component Fragment in pac#age org. apache.wicket.mark"p.html.panel. Kust li#e its parent component WebMark"pContainer* Fragment doesnBt ha.e its own mar#up file but it uses a mar#up fragment defined in the mar#up file of its parent container* which can be a page or a panel. The fragment must be delimited with tag <Cicket:%ragment> and must be identified by a Cicket:id attribute. -n addition to the component id* FragmentBs constructor ta#es as input also the id of the fragment and a reference to its container. -n the following e,ample we ha.e defined a fragment in a page and we used it as content area( Page mar#up(
<html> ... <bod"> ... <di4 Cicket:id89content5rea9></di4> <Cicket:%ragment Cicket:id89%ragment$d9> <F-- 3ragment markup goes here --> </Cicket:%ragment> </bod"> </html>

Page code(
3ragment %ragment 8 neC add7%ragment:1 3ragment 79content5rea9, 9%ragment$d9, this:1

=ragments can be .ery helpful with comple, pages or components. =or e,ample letBs say that we ha.e a page where users can register to our forum. This page should first display a form where user must insert his/her personal data (name* username* password* email and so on)* then* once the user has submitted1% the form* the page should display a message li#e F'our registration is complete; Please chec# your mail to acti.ate your user profile.G. -nstead of displaying this message with a new component or in a new page* we can define two
10 (orm component will be introduced in chapter >

Wicket free user guide

47

3 ;eeping control over HT/0

fragments( one for the initial form and one to display the confirmation message. The second fragment will replace the first one after the form has been submitted( Page mar#up(
<html> ... <bod"> ... <di4 Cicket:id89content5rea9></di4> <Cicket:%ragment Cicket:id89%orm3rag9> <F-- 3orm markup goes here --> </Cicket:%ragment> <Cicket:%ragment Cicket:id89message3rag9> <F-- ;essage markup goes here --> </Cicket:%ragment> </bod"> </html>

Page code(
3ragment %ragment 8 neC add7%ragment:1 //... //%orm has been submitted 3ragment %ragment 8 neC 3ragment 79content5rea9, 9message3rag9, this:1 replace7%ragment:1 3ragment 79content5rea9, 9%orm3rag9, this:1

#.- Adding header contents to the final page


PanelBs mar#up can also contain 9T<: tags which must go inside header section of the final page* li#e tags <script> or <st"le>. To tell 2ic#et to put these tags inside page <head>* we must surround them with the <Cicket:head> tag. !onsidering the mar#up of a generic panel* we can use <Cicket:head> tag in this way(
<Cicket:head> <script t"pe89text/2a4ascript9> %unction m"#anel3unction7: & </script> <st"le> .m"#anelClass %ont-Ceight: bold1 color: red1 & </st"le> </Cicket:head> <bod"> <Cicket:panel> ... </Cicket:panel> ... </bod">

Wicket free user guide

48

3 ;eeping control over HT/0

2ic#et will ta#e care of placing the content of <Cicket:head> inside the <head> tag of the final page. >ote The <Cicket:head> tag can also be used with children pages/panels which e,tend parent mar#up using tag <Cicket:extend>. >ote The content of the <Cicket:head> tag is added to the header section once per component class. -n other words* if we add multiple instances of the same panel to a page* the <head> tag will be populated Hust once with the content of <Cicket:head>. Warning The <Cicket:head> tag is ideal if we want to define small in-line bloc#s of !"" or Ka.a"cript. 9owe.er 2ic#et pro.ides also a more sophisticated techniEue to let components contribute to header section with in-line bloc#s and resource files li#e !"" or Ka.a"cript files. 2e will see this techniEue later in chapter 1$.

#.' 0sing stu= markup in our pagesIpanels


2ic#etBs <Cicket:remo4e> tag can be .ery useful when our web designer needs to show us how a page or a panel should loo# li#e. The mar#up inside this tag will be stripped out in the final page* so itBs the ideal place for web designers to put their stub mar#up(
<html> <head> ... </head> <bod"> ... <Cicket:remo4e> <F-- )tub markup goes here --> </Cicket:remo4e> </bod"> </html>

#.2 How to render component =od onl


2hen we bind a component to its corresponding tag we can choose to get rid of this outer tag in the final mar#up. -f we call method set)ender1od,+nl,(tr"e on a component 2ic#et will remo.e the surrounding tag. =or e,ample gi.en the following mar#up and code( <ar#up(
<html> <head> <title>Dello Corld page</title> </head>

Wicket free user guide

$%

3 ;eeping control over HT/0

<bod"> <di4 Cicket:id89helloWorld9>HhelloWorldJ</di4> </bod"> </html>

Ka.a code(
/abel label 8 neC /abel79helloWorld9, QDello WorldFN:1 label.set*ender.od"'nl"7true:1 add7label:1

the output will be(


<html> <head> <title>Dello Corld page</title> </head> <bod"> Dello WorldF </bod"> </html>

As you can see the <di4> tag used for component Label is not present in the final mar#up.

#.4 Hiding decorating elements with the <wicket:enclosure> tag


@ur data are rarely displayed alone without a caption or other graphic elements that ma#e clear the meaning of their .alue. =or e,ample(
<label>Total amount: </label><span Cicket:id89total5mount9></span>

2ic#et comes with a nice utility tag called <Cicket:enclosure> that automatically hides those decorating elements if the related data .alue is not .isible. All we ha.e to do is to put the in.ol.ed mar#up inside this tag. Applying <Cicket:enclosure> to the pre.ious e,ample we get the following mar#up(
<Cicket:enclosure> <label>Total amount: </label><span Cicket:id89total5mount9></span> </Cicket:enclosure>

ow if component total5mount is not .isible* its description (Total amount:) will be automatically hidden. -f we ha.e more then a 2ic#et component inside <Cicket:enclosure> we can use child attribute to specify which component will control the o.erall .isibility(
<Cicket:enclosure child89total5mount9> <label>Total amount: </label><span Cicket:id89total5mount9></span><br/> <label>(xpected deli4er" date: </label><span Cicket:id89deli4+ate9></span> </Cicket:enclosure>

Wicket free user guide

$1

3 ;eeping control over HT/0

child

attribute supports also nested components with a colon-separated path(


<Cicket:enclosure child89total5mountContainer:total5mount9> <di4 Cicket:id89total5mountContainer9> <label>Total amount: </label><span Cicket:id89total5mount9></span> </di4> <label>(xpected deli4er" date: </label><span Cicket:id89deli4+ate9></span> </Cicket:enclosure>

#.1/ 8urrounding existing markup with ;order


!omponent org.apache.wicket.mark"p.html.border.1order is a special purpose container created to enclose its tag body with its related mar#up. Kust li#e panels and pages* borders also ha.e their own mar#up file which is defined following the same rules seen for panels and pages. -n this file <Cicket:border> tag is used to indicate which part of the content is to be considered as border mar#up(
<?xml 4ersion89@.A9 encoding890T3-B9?> <html xmlns89http://CCC.CR.org/@SSS/xhtml9 xmlns:Cicket89http://Cicket.apache.org9> <head></head> <bod"> <F-e4er"thing abo4e <Cicket:border> tag Cill be discarded...--> <di4> %oo<br /> <Cicket:bod"/><br /> buP <br /> </di4> </Cicket:border> <F-</bod"> </html> e4er"thing beloC </Cicket:border> tag Cill be discarded...--> <Cicket:border>

The <Cicket:bod"/> tag used in the e,ample abo.e is used to indicate where the body of the tag will be placed inside border mar#up. ow if we attached this border to the following tag
<span Cicket:id89m".order9> bar </span>

we would obtain the following resulting 9T<:(


<span Cicket:id89m".order9> <di4> %oo<br /> bar<br /> buP <br /> </di4> </span>

1order can also contain children components which can be placed either inside its mar#up file or
Wicket free user guide

$4

3 ;eeping control over HT/0

inside its corresponding 9T<: tag. -n the first case children must be added to the border component with method add/o1order(Component... * while in the second case we must use the add (Component... method. The following e,ample illustrates both use cases( Border class(
public class ;".order extends .order public ;".order7)tring id: super7id:1 & &

Border mar#up(
<?xml 4ersion89@.A9 encoding890T3-B9?> <html xmlns89http://CCC.CR.org/@SSS/xhtml9 xmlns:Cicket89http://Cicket.apache.org9> <head></head> <bod"> <Cicket:border> <di4> <di4 Cicket:id89child;arkup9></di4> <Cicket:bod"/><br /> </di4> </Cicket:border> </bod"> </html>

Border tag(
<di4 Cicket:id89m".order9> <span Cicket:id89childTag9></span> </di4>

-nitialiCation code for border11(


;".order m".order 8 neC ;".order79m".order9:1 m".order.addTo.order7neC /abel79child;arkup9, 9Child inside markup.9::1 m".order.add7neC /abel79childTag9, 9Child inside tag.9::1 add7m".order:1

#.11 8ummar
-n this chapter we ha.e seen the tools pro.ided by 2ic#et to gain complete control o.er the generated 9T<:. 9owe.er we didnBt see yet how we can repeat a portion of 9T<: with 2ic#et. 2ith classic ser.er-side technologies li#e P9P or K"P we use loops (li#e while or 0or) inside our pages to achie.e this result.
11 nitiali<ation code should go inside component:s constructor or inside its method on nitiali<e 4we will see this method in the next chapter5

Wicket free user guide

$$

3 ;eeping control over HT/0

To perform this tas# 2ic#et pro.ides a special-purpose family of components called repeaters and designed to repeat their mar#up body to display a set of items. But to fully understand how these components wor#* we must first learn more of 2ic#etBs basics. ThatBs why repeaters will be introduced later in chapter 11.

Wicket free user guide

$3

9 Components lifecycle

& 'omponents lifecycle


Kust li#e applets14 and ser.lets1$* also 2ic#et components follow a lifecycle during their e,istence. -n this chapter we will analyCe each stage of this cycle and we will learn how to ma#e the most of the hoo# methods that are triggered when a component mo.es from one stage to another.

(.1 ,ifec cle stages of a component


During its life a 2ic#et component goes through three basic stages( 1. !nitiali6ation: a component is instantiated by 2ic#et and prepared for the rendering phase. 4. 3endering: in this stage 2ic#et generates component mar#up. -f a component contains children (i.e. is a subclass of Mark"pContainer) it must first wait for them to be rendered before starting its own rendering. $. 3emoving: this stage is triggered when a component is e,plicitly remo.ed from its component hierarchy* i.e. when its parent in.o#es remo!e(component on it. This stage is facultati.e and is ne.er triggered for pages. The following picture shows the state diagram of component lifecycle(

-nitialiCing

+endering

+emo.ing

@nce a component has been remo.ed it can be added again to a container* but the initialiCation stage wonBt be e,ecuted again. >ote -f you read the Ka.aDoc of class Component you will find a more detailed description of component lifecycle. 9owe.er this description introduces some ad.anced topics we didnBt co.ered yet hence* to a.oid confusion* in this chapter some details ha.e been omitted and they will be co.ered later in the ne,t chapters. =or now you can consider Hust the simplified .ersion of the lifecycle described abo.e.

(.2 Hook methods for component lifec cle


!lass Component comes with a number of hoo# methods that can be o.erridden in order to customiCe
12 'ee http: download.oracle.com -avase tutorial deployment applet life(ycle.html 13 'ee +'ervlet 0ife Cycle - paragraph of 'ervlet 'pecification document

Wicket free user guide

$5

9 Components lifecycle

component beha.ior during its lifecycle. -n the following table these methods are grouped according to the stage in which they are in.o#ed (and they are sorted by e,ecution order)(

C cle sta!e
!nitiali6ation

"nvolved met#ods
on-nitialiCe on!onfigure onBefore+ender on+ender on!omponentTag on!omponentTagBody onAfter+ender!hildren onAfter+ender on+emo.e

3endering

3emoving

ow letBs ta#e a closer loo# at each stage and to at hoo# methods.

(.3 "nitiali$ation stage


This stage is performed at the beginning of the component lifecycle. During initialiCation* the component has already been inserted into its component hierarchy so we can safely access to its parent container or to its page with methods getParent( or getPage( . The only method triggered during this stage is on2nitiali3e( . This method is a sort of FspecialG constructor where we can e,ecute a custom initialiCation of our component. "ince on2nitiali3e is similar to a regular constructor* when we o.erride this method we ha.e to call s"per.on2nitiali3e inside its body* usually as first instruction.

(.# Renderin! stage


This stage is triggered each time a component is rendered by 2ic#et* typically when its page is reEuested or when it is refreshed .ia AKAL13.

(.#.1

+ethod on.onfigure

<ethod onCon0ig"re( has been introduced in order to pro.ide a good point to manage the component states such as its .isibility or enabled state. This method is called before the render phase starts. As stated in paragraph 3.1* is-isible and is'nabled are called multiple times when a page or a component is rendered* so itBs highly recommended not to directly o.erride these method* but rather to use onCon0ig"re to change component states. @n the contrary method on1e0ore)ender (see the ne,t paragraph) is not indicated for this tas# because it will not be in.o#ed if component .isibility is set to false.

(.#.2

+ethod on;efore3ender

The most important hoo# method of this stage is probably on1e0ore)ender( . This method is called before a component starts its rendering phase and it is our last chance to change its children hierarchy. -f we want add/remo.e children components this is the right place to do it.
14 7)7? support will be discussed in chapter 18$

Wicket free user guide

$A

9 Components lifecycle

-n the ne,t e,ample (proHect %ife(ycleStages) we will create a page which alternately displays two different labels* swapping between them each time it is rendered(
public class Dome#age extends Web#age pri4ate /abel %irst/abel1 pri4ate /abel second/abel1 public Dome#age7: %irst/abel 8 neC /abel79label9, 93irst label9:1 second/abel 8 neC /abel79label9, 9)econd label9:1 add7%irst/abel:1 add7neC /ink79reload9: !'4erride public 4oid onClick7: & &:1 & !'4erride protected 4oid on.e%ore*ender7: i%7contains7%irst/abel, true:: replace7second/abel:1 else replace7%irst/abel:1 super.on.e%ore*ender7:1 & &

The code inside on1e0ore)ender( is Euite tri.ial as it Hust chec#s which label among 0irstLabel and secondLabel is currently inserted into the component hierarchy and it replaces the inserted label with the other one. This method is also responsible for in.o#ing children on1e0ore)ender( so if we decide to o.erride it we ha.e to call s"per.on1e0ore)ender( . 9owe.er* unli#e on2nitiali3e( , the call to superclass method should be placed at the end of methodBs body in order to affect childrenBs rendering with our custom code. Please note that in the e,ample abo.e we can trigger the rendering stage pressing =5 #ey or clic#ing on lin# FreloadG. Warning -f we forget to call superclass .ersion of methods on2nitiali3e( or on1e0ore)ender( * 2ic#et will throw an 2llegalState'(ception with the following message(
2a4a.lang.$llegal)tate(xception: org.apache.Cicket.Component has not been properl" initialiPed. )omething in the hierarch" o% <page class name> has not called super.on$nitialiPe7:/on.e%ore*ender7: in the o4erride o% on$nitialiPe7:/ on.e%ore*ender7: method

(.#.3

+ethod on.omponent*ag

<ethod onComponent/ag(Component/ag is called to process component tag* which can be freely


Wicket free user guide

$6

9 Components lifecycle

manipulated through its argument of type org.apache.wicket.mark"p.Component/ag. =or e,ample we can add/remo.e tag attributes with methods p"t(String ke,4 String !al"e and remo!e (String ke, * or we can e.en decide to change the tag or rename it with method setName(String (the following code is ta#en from proHect 2n(omponent!ag#0ample)( <ar#up code(
<head> <meta charset89ut%-B9 /> <title></title> </head> <bod"> <h@ Cicket:id89hello;essage9></h@> </bod">

Ka.a code(
public class Dome#age extends Web#age public Dome#age7: add7neC /abel79hello;essage9, 9Dello World9: !'4erride protected 4oid onComponentTag7ComponentTag tag: super.onComponentTag7tag:1 //Turn the h@ tag to a span tag.setName79span9:1 //5dd %ormatting st"le tag.put79st"le9, 9%ont-Ceight:bold9:1 & &:1 //... & &

0nerated mar#up(
<head> <meta charset89ut%-B9 /> <title></title> </head> <bod"> <span Cicket:id89hello;essage9 st"le89%ont-Ceight:bold9>Dello World</span> </bod">

Kust li#e we do with on2nitiali3e* if we decide to o.erride onComponent/ag we must remember to call the same method of the super class because also this class may also customiCe the tag. @.erriding onComponent/ag is perfectly fine if we ha.e to customiCe the tag of a specific component* but if we wanted to reuse the code across different components we should consider to use a beha.ior in place of this hoo# method. 2e ha.e already seen in paragraph 3.4 how to use beha.ior Attrib"teModi0ier to manipulate the tagBs attribute. -n paragraph 15.1 we will see that base class 1eha!ior offers also a callbac# method named onComponent/ag(Component/ag4 Component that can be used in place of the hoo# method onComponent/ag(Component/ag .

(.#.#

+ethods on.omponent*ag;od

Wicket free user guide

$7

9 Components lifecycle

<ethod onComponent/ag1od,(Mark"pStream4 Component/ag is called to process the component tagBs body. Kust li#e onComponent/ag it ta#es as input a Component/ag parameter representing the component tag. -n addition* we also find a Mark"pStream parameter which represents the page mar#up stream that will be sent bac# to the client as response. onComponent/ag1od, can be used in combination with the ComponentBs method replace Component/ag1od, to render a custom body under specific conditions. =or e,ample (ta#en from proHect 2n(omponent!ag#0ample) we can display a brief description instead of the body if the label component is disabled(
public class Dome#age extends Web#age public Dome#age7: //... add7neC /abel79hello;essage9, 9Dello World9: !'4erride protected 4oid onComponentTag.od"7;arkup)tream markup)tream, ComponentTag tag: i%7Fis(nabled7:: replaceComponentTag.od"7markup)tream, tag, 97the component is disabled:9:1 else super.onComponentTag.od"7markup)tream, tag:1 & &:1 & &

ote that the original .ersion of onComponent/ag1od, is in.o#ed only when we want to preser.e the standard rendering mechanism for the tagBs body (in our e,ample this happens when the component is enabled).

(.( Removin! stage


This stage is triggered when a component is remo.ed from its component hierarchy. The only hoo# method for this phase is on)emo!e( . -f our component still holds some resources needed during rendering phase* we can o.erride this method to release them. @nce a component has been remo.ed we are free to add it again to the same container or to a different one.

(.- 8ummar
-n this chapter we ha.e seen which stages compose the lifecycle of 2ic#et components and which hoo# methods they pro.ide. @.erriding these methods we can dynamically modify the component hierarchy and we can enrich the beha.ior of our custom components.

Wicket free user guide

$8

8 Page versioning and caching

( Page versioning and caching


This chapter e,plains how 2ic#et manages page instances* underlining the difference between stateful and stateless pages. The chapter also introduces some ad.anced topics li#e Ka.a "erialiCation and multi-le.el cache. 9owe.er* to understand what you will read you are not reEuired to be familiar with these arguments.

-.1 8tateful pages E8 stateless


2ic#et pages can be di.ided into two categories( stateful and stateless pages. "tateful pages are those which rely on user session to store they internal state and to #eep trac# of user interaction. @n the contrary stateless pages are those which donBt change their internal state during their lifecycle and they donBt need to occupy space into user session. =rom 2ic#etBs point of .iew the biggest difference between these two types of page is that stateful pages are versioned, meaning that they will be sa.ed into user session e.ery time their internal state has changed. 2ic#et automatically assigns a session to the user the first time a stateful page is reEuested. Page .ersions are stored into user session using 7ava 8eriali6ation mechanism. "tateless pages are ne.er .ersioned and thatBs why they donBt reEuire a .alid user session. -f we want to #now whether a page is stateless or not* we can call the isPageStateless( method of class Page. -n order to build a stateless page we must comply with some rules to ensure that the page wonBt need to use user session. These rules are illustrated in paragraph A.$ but before tal#ing about stateless pages we must first understand how stateful pages are handled and why they are .ersioned.

-.2 8tateful pages


"tateful pages are .ersioned in order to support browserBs bac# button( when this button is pressed 2ic#et must respond by rendering the same page instance pre.iously used. A new page .ersion is created when a stateful page is reEuested for the first time or when an e,isting instance is modified (for e,ample changing its component hierarchy). To identify each page .ersion 2ic#et uses a session-relati.e identifier called page id. This is a progressi.e number and it is increased e.ery time a new page .ersion is created. -n the final e,ample of the pre.ious chapter (proHect %ife(ycleStages)* you may ha.e noticed the number appended at the and of &+:. This number is the page id we are tal#ing about(

llustration 8$1% Page id at the end of @A0 -n this chapter we will use a re.ised .ersion of this e,ample proHect where the component hierarchy is modified inside the LinkBs onClick( method. This is necessary because 2ic#et creates a new page

Wicket free user guide

3%

8 Page versioning and caching

.ersion only if the page is modified before its method on1e0ore)ender( is in.o#ed. The code of the new home page is the following(
public class Dome#age extends Web#age pri4ate static %inal long serialOersion0$+ 8 @/1 pri4ate /abel %irst/abel1 pri4ate /abel second/abel1 public Dome#age7: %irst/abel 8 neC /abel79label9, 93irst label9:1 second/abel 8 neC /abel79label9, 9)econd label9:1 add7%irst/abel:1 add7neC /ink79reload9: !'4erride public 4oid onClick7: i%7get#age7:.contains7%irst/abel, true:: get#age7:.replace7second/abel:1 else get#age7:.replace7%irst/abel:1 & &:1 & &

ow if we run the new e,ample (proHect %ife(ycleStages"evisited) and we clic# on the F+eloadG button* a new page .ersion is created and the page id is increased by one(

llustration 8$*% pressing +Aeload- button causes page id to increment -f we press the bac# button the page .ersion pre.iously rendered (and serialiCed) will be retrie.ed (i.e. deserialiCed) and it will be used again to respond to our reEuest (and page id is decremented)(

llustration 8$1% pressing +Back- button we can go back to the previous page version 4page id is decremented5

Wicket free user guide

31

8 Page versioning and caching

>ote =or more details about page storing you can .isit the wi#i page at https(//cwi#i.apache.org/confluence/display/2-!MIT/PageN"torage. @n this page you can find which classes are in.ol.ed into page storing mechanism and how they wor# together. As we ha.e stated at the beginning of this chapter* page .ersions are stored using Ka.a serialiCation* therefore e.ery obHect referenced inside a page must be serialiCable 15. -n paragraph 8.A we will see how to o.ercome this limit and wor# with non-serialiCable obHects in our components using detachable 2ic#et models.

-.2.1

0sing a specific page version with Page3eference

To retrie.e a specific page .ersion in our code we can use class org.apache.wicket. Page)e0erence by pro.iding its constructor with the corresponding page id(
//load page 4ersion Cith page id 8 R #age*e%erence page*e%erence 8 neC #age*e%erence7R:1 //load the related page instance #age page 8 page*e%erence.get#age7:1

To get the related page instance we must use method getPage.

-.2.2

*urning off page versioning

-f for any reason we need to switch off .ersioning for a gi.en page* we can call its method set-ersioned(0alse .

-.2.3

Plugga=le seriali6ation

"tarting from .ersion 1.5 it is possible to choose which implementation of Ka.a serialiCation will be used by 2ic#et to store page .ersions. 2ic#et serialiCes pages using an implementation of interface org.apache.wicket.seriali3e.2Seriali3er. The default implementation is org.apache .wicket.seriali3e.5a!a..a!aSeriali3er and it uses the standard Ka.a serialiCation mechanism based on classes +b5ect+"tp"tStream and +b5ect2np"tStream. 9owe.er on -nternet we can find other interesting serialiCation libraries li#e Mryo1A which performs faster then the standard implementation. The serialiCer in use can be customiCed with the setSeriali3er(2Seriali3er method defined by setting interface org.apache.wicket.settings.2FrameworkSettings. 2e can access this interface inside the method init of the class Application using the getFrameworkSettings( method (
!'4erride public 4oid init7: super.init7:1 get3rameCork)ettings7:.set)erialiPer7"our)erialiPer:1 &

A erialiCer based on Mryo library is pro.ided by the 2ic#et"tuff proHect. 'ou can find more information on this proHect* as well as the instructions to use its modules* in Appendi, B.
15 t must implement standard interface #ava$io$'eriali<ation 16 http: code.google.com p kryo

Wicket free user guide

34

8 Page versioning and caching

-.2.#

Page caching

By default 2ic#et persists .ersions of pages into a session-relati.e file on dis#* but it uses a two-le.els cache to speed up this process. The first le.el of the cache uses a http session attribute called Fwic#et(persistentPage<anagerData->APP:-!AT-@ O A<I?G to store pages. The second le.el cache stores pages into application-scoped .ariables which are identified by a session id and a page id. The following picture is an o.er.iew of these two caching le.els(

llustration 8$3% 7n overview of Wicket cache structure The session-scoped cache is faster then the other memory le.els but it contains only the pages used to ser.e the last reEuest. 2ic#et allows us to set the ma,imum amount of memory allowed for the application-scoped cache and for the page store file. Both parameters can be configured .ia setting interface org.apache .wicket.settings.2StoreSettings. This interface pro.ides the setMa(Si3ePerSession(1,tes b,tes method to set the siCe for page store file. The 1,tes parameter is the ma,imum siCe allowed for this file(
!'4erride public 4oid init7: super.init7:1 get)tore)ettings7:.set;ax)iPe#er)ession7."tes.kilob"tes7TAA::1 &

!lass org.apache.wicket."til.lang.1,tes is an utility class pro.ided by 2ic#et to e,press siCe in bytes (for further details refer to the Ka.aDoc). =or the second le.el cache we can use the set2nmemor,CacheSi3e(int inmemor,CacheSi3e method. The integer parameter is the ma,imum number of page instances that will be sa.ed into application-scoped cache(
!'4erride public 4oid init7: super.init7:1 get)tore)ettings7:.set$nmemor"Cache)iPe7TA:1 &

-.2.(

Page expiration

Page instances are not #ept in the user session fore.er. They can be discarded when the limit set with the setMa(Si3ePerSession method is reached or (more often) when user session e,pires. 2hen we as# 2ic#et for a page id corresponding to a page instance remo.ed from the session* we bump into a

Wicket free user guide

3$

8 Page versioning and caching

Page'(pired'(ception and we get the following default error page(

This error page can be customiCed with the setPage'(pired'rrorPage method of the org.apache.wicket.settings.2ApplicationSettings interface(
!'4erride public 4oid init7: super.init7:1 get5pplication)ettings7:.set#age(xpired(rror#age7Custom(xpired(rror#age.class:1 &

The page class pro.ided as custom error page must ha.e a public constructor with no argument or a constructor that ta#es as input a single PageParameters argument (the page must be bookmarkable as described in paragraph 7.1.1).

-.3 8tateless pages


2ic#et ma#es it .ery easy to build stateful pages* but sometimes we might want to use an Fold schoolG stateless page that doesnBt #eep memory of its state in the user session. =or e,ample consider the public area of a site or a login page( in those cases a stateful page would be a waste of resources or e.en a security threat* as we will see in paragraph 1%.8. -n 2ic#et a page can be stateless only if it satisfies the following reEuirements( 1. it has been instantiated by 2ic#et (i.e. we donBt create it with operator neC ) using a constructor with no argument or a constructor that ta#es as input a single PageParameters argument (class PageParameters will be co.ered in chapter 7). 4. All its children components (and beha.iors 16) are in turn stateless* which means that their method isStateless must return true. The first reEuirement implies that* rather than creating a page by hand* we should rely on 2ic#etBs capability of resol.ing page instances* li#e we do when we use method set)esponsePage(Class page . -n order to comply with the second reEuirement it could be helpful to chec# if all children components of a page are stateless. To do this we can le.erage method !isitChildren and the .isitor pattern to iterate o.er components and test if their method isStateless actually returns true(
!'4erride protected 4oid on$nitialiPe7: super.on$nitialiPe7:1 4isitChildren7neC $Oisitor<Component, Ooid>7:
17 'ee method get'tatelessHint in paragraph 19$1

Wicket free user guide

33

8 Page versioning and caching

!'4erride public 4oid component7Component component, $Oisit<Ooid> arg@: i%7Fcomponent.is)tateless7:: )"stem.out.println79Component 9 > component.get$d7: > 9 is not stateless9:1 & &:1 &

Alternati.ely* we could use the StatelessComponent utility annotation along with the StatelessChecker class (they are both in pac#age org.apache.wicket.de!"tils. stateless). StatelessChecker will throw an 2llegalArg"ment'(ception if a component annotated with StatelessComponent doesnBt respect the reEuirements for being stateless. To use StatelessComponent annotation we must first add the StatelessChecker to our application as a component render listener(
!'4erride public 4oid init7: super.init7:1 getComponent#ost'n.e%ore*ender/isteners7:.add7neC )tatelessChecker7::1 &

>ote <ost of the 2ic#etBs built-in components are stateful* hence they can not be used with a stateless page. 9owe.er some of them ha.e also a stateless .ersion which can be adopted when we need to #eep a page stateless. -n the rest of the guide we will point out when a built-in component comes also with a stateless .ersion. A page can be also e,plicitly declared as stateless setting the appropriate flag to true with the setStatelessHint(tr"e method. This method will not pre.ent us from .iolating the reEuirements for a stateless page* but if we do so we will get the following warning log message(
#age I<page class>I is not stateless because o% component Cith path I<component path>I

-.# 8ummar
-n this chapter we ha.e seen how page instances are managed by 2ic#et. 2e ha.e learnt that pages can be di.ided into two families( stateless and stateful pages. Mnowing the difference between the two types of pages is important to build the right page for a gi.en tas#. 9owe.er* to complete the discussion about stateless pages we still ha.e to deal with two topics we ha.e Hust outlined in this chapter( class PageParameters and bookmarkable pages. The first part of chapter 7 will co.er these missing topics.

Wicket free user guide

35

2 @nder the hood of the re&uest processing

) *nder the hood of the re+uest processing


Although 2ic#et was born to pro.ide a reliable and comprehensi.e obHect oriented abstraction for web de.elopment* sometimes we might need to wor# directly with FrawG web entities such as user session* web reEuest* Euery parameters* and so on. =or e,ample this is necessary if we want to store an arbitrary parameter in the user session. 2ic#et pro.ides wrapper classes that allow us to easily access to web entities without the burden of using the low-le.el AP-s of Ka.a "er.let "pecification. 9owe.er it will always be possible to access standard classes (li#e HttpSession* HttpSer!let)e6"est* etc...) that lay under our 2ic#et application. This chapter will introduce these wrapper classes and it will e,plain how 2ic#et uses them to handle the web reEuests initiated by the userBs browser.

'.1 .lass Application and re1uest processing


Beside configuring and initialiCing our application* the Application class is responsible for creating the internal entities used by 2ic#et to process a reEuest. These entities are instances of the following classes( )e6"estC,cle* )e6"est* )esponse and Session. The ne,t paragraphs will illustrate each of these classes* e,plaining how they are in.ol.ed into reEuest processing.

'.2

Re%uest and Response classes

The )e6"est and )esponse classes are located in pac#age org.apache.wicket.re6"est and they pro.ide an abstraction of the concrete reEuest and response used by our web application. Both classes are declared as abstract but if our application class inherits from WebApplication it will use their sub classes Ser!letWeb)e6"est and Ser!letWeb)esponse* both of them located inside the pac#age org.apache.wicket.protocol.http.ser!let. Ser!letWeb)e6"est and Ser!letWeb)esponse wrap respecti.ely a HttpSer!let)e6"est and a HttpSer!let)esponse obHect. -f we need to access to these low-le.el obHects we can call )e6"estBs method getContainer)e6"est( and )esponseBs method getContainer )esponse( .

'.3 *he $director& of re1uest processing: 3e1uest. cle


!lass org.apache.wicket.re6"est.c,cle.)e6"estC,cle is the entity in charge of ser.ing a web reEuest. @ur application class creates a new )e6"estC,cle on e.ery reEuest with its method create)e6"estC,cle(re6"est4 response . <ethod create)e6"estC,cle is declared as 0inal* so we canBt o.erride it to return a custom subclass of )e6"estC,cle. -nstead* we must build a re5uest cycle provider implementing interface org.apache.wicket.2)e6"estC,clePro!ider* and then we must tell our application class to use it .ia the set)e6"estC,clePro!ider method. The current running reEuest cycle can be retrie.ed at any time by calling its static method )e6"estC,cle.get( . "trictly spea#ing this method returns the reEuest cycle associated with the current 7or local8 thread, which is the thread that is ser.ing the current reEuest. A similar get( method is also implemented in classes org.apache.wicket.Application (as we
Wicket free user guide

3A

2 @nder the hood of the re&uest processing

ha.e seen in paragraph 4.4.4) and org.apache.wicket.Session in order to get the application and the session in use by the current thread. >ote The implementation of the get method ta#es ad.antage of the standard class 5a!a.lang./hreadLocal. "ee its Ka.aDoc for an introduction to local-thread .ariables. !lass org.apache.wicket.Component pro.ides the get)e6"estC,cle( con.enience method that internally in.o#es )e6"estC,cle.get( (
public %inal *eEuestC"cle get*eEuestC"cle7: return *eEuestC"cle.get7:1 &

method which is a

'.3.1

3e1uest. cle and re1uest processing


>ote This paragraph will pro.ide Hust the basic informations about what happens behind the scenes of reEuest processing. 2hen you wor# with 2ic#et itBs unli#ely to ha.e a need for customiCing this process* so we wonBt co.er this topic in detail.

-n order to process a reEuest* )e6"estC,cle delegates the tas# to another entity which implements interface org.apache.wicket.re6"est.2)e6"estHandler. There are different implementations of this interface* each suited for a particular type of reEuested resource (a page to render* an AKAL reEuest* an &+: to an e,ternal page* etc...). To resol.e the right handler for a gi.en 9TTP reEuest* the )e6"estC,cle uses a set of obHects implementing the org.apache.wicket.re6"est.2)e6"estMapper interface. The mapping interface defines the getCompatibilit,Score()e6"est re6"est method which returns a score indicating how compatible the reEuest mapper is for the current reEuest. )e6"estC,cle will choose the mapper with the highest score and it will call its map)e6"est()e6"est re6"est method to get the proper handler for the gi.en reEuest. @nce )e6"estC,cle has resol.ed a reEuest handler* it in.o#es its method respond(2)e6"estC,cle re6"estC,cle to start reEuest processing. The following seEuence diagram recaps how a reEuest handler is resol.ed by the )e6"estC,cle(

Wicket free user guide

36

2 @nder the hood of the re&uest processing

De.elopers can create additional implementations of 2)e6"estMapper and add them to their application .ia the mo"nt(2)e6"estMapper mapper method of the WebApplication class. -n paragraph 7.A we will see how 2ic#et uses this method to add built-in mappers for mounted pages.

'.3.2

Generating 03, with the url&or and map'rl&or methods

The )e6"estC,cle is also responsible for generating the &+: .alue (as CharSe6"ence) for the following entities( a page class* .ia the "rlFor(Class7C8 pageClass4 PageParameters parameters method an 2)e6"estHandler .ia the "rlFor(2)e6"estHandler handler method a )eso"rce)e0erence .ia the "rlFor()eso"rce)e0erence re0erence4 PageParameters params method (resource entities will be introduced in chapter 1$). The o.erloaded "rlFor method from abo.e also has a corresponding .ersion that returns an instance of org.apache.wicket.re6"est.9rl instead of a CharSe6"ence. This .ersion has the prefi, BmapB in its name (i.e. it has map9rlFor as full name).

'.3.3

+ethod set3esponsePage

The )e6"estC,cle class contains the implementation of the set)esponsePage method we use to redirect a user to a specific page (see paragraph 4.3). The namesa#e method of class org.apache.wicket. Component is Hust a con.enience method that internally in.o#es the actual implementation on current reEuest cycle(
public %inal 4oid set*esponse#age7%inal #age page: get*eEuestC"cle7:.set*esponse#age7page:1 &

'.3.#

3e1uest. cleAs hook methods and listeners

The )e6"estC,cle comes with some hoo# methods which can be o.erridden to perform custom actions when reEuest handling reaches a specific stage. These methods are( on;egin3e1uestJ@: called when the )e6"estC,cle is about to start handling the reEuest. onDnd3e1uestJ@: called when the )e6"estC,cle has finished to handle the reEuest on5etachJ@: called after the reEuest handling has completed and the )e6"estC,cle is about to be detached from its thread. The default implementation of this method in.o#es detach( on the current session (the Session class will be shortly discussed in paragraph 6.3). <ethods on1e0ore)e6"est and on'nd)e6"est can be used if we need to e,ecute custom actions before and after business code is e,ecuted* such as opening a 9ibernate/KPA session and closing it when code has terminated. A more fle,ible way to interact with the reEuest processing is to use the listener interface org.apache.wicket.re6"est.c,cle.2)e6"estC,cleListener. -n addition to the three methods already seen for )e6"estC,cle* this interface offers further hoo#s into reEuest processing( on;egin3e1uestJ3e1uest. cle c cle@: 7see the description above8 onDnd3e1uestJ3e1uest. cle c cle@: 7see the description above8 on5etachJ3e1uest. cle c cle@: 7see the description above8 on3e1uestHandler3esolvedJ3e1uest. cle c cleG !3e1uestHandler handler@: called when an 2)e6"estHandler has been resol.ed. on3e1uestHandler8cheduledJ3e1uest. cle c cleG !3e1uestHandler handler@: called when an 2)e6"estHandler has been scheduled for e,ecution.

Wicket free user guide

37

2 @nder the hood of the re&uest processing

on3e1uestHandlerDxecutedJ3e1uest. cle c cleG !3e1uestHandler handler@: called when an 2)e6"estHandler has been e,ecuted. onDxceptionJ3e1uest. cle c cleG Dxception ex@: called when an e,ception has been thrown during reEuest processing. onDxception3e1uestHandler3esolvedJ3e1uest. cle rcG !3e1uestHandler rhG Dxception ex@: called when an 2)e6"estHandler has been resol.ed and will be used to handle an e,ception. on0rl+appedJ3e1uest. cle c cleG !3e1uestHandler handlerG 0rl url@: called when an &+: has been generated for an 2)e6"estHandler obHect.

To use the reEuest cycle listeners we must add them to our application which in turn will pass them to the new )e6"estC,cleBs instances created with create)e6"estC,cle method(
!'4erride public 4oid init7: super.init7:1 $*eEuestC"cle/istener m"/istener1 //listener initialiPation... get*eEuestC"cle/isteners7:.add7m"/istener: &

The get)e6"estC,cleListeners method returns an instance of class org.apache.wicket. re6"est.c,cle.)e6"estC,cleListenerCollection. This class is a sort of typed collection for 2)e6"estC,cleListener and it also implements the !omposite pattern17.

'.# 8ession .lass


-n 2ic#et we use class org.apache.wicket.Session to handle session-relati.e informations such as client informations* session attributes* session-le.el cache (seen in paragraph A.4.3)* etc... -n addition* we #now from paragraph A.1 that 2ic#et creates a user session to store .ersions of stateful pages. "imilarly to what happens with )e6"estC,cle* the new SessionBs instances are generated by the Application class with the newSession()e6"est re6"est4 )esponse response method. This method is not declared as 0inal* hence it can be o.erridden if we need to use a custom implementation of the Session class. By default if our custom application class is a subclass of WebApplication* method newSession will return an instance of class org.apache.wicket.protocol.http.WebSession. As we ha.e mentioned tal#ing about )e6"estC,cle* also class Session pro.ides a static get( method which returns the session associated to the current thread.

'.#.1

8ession and listeners

"imilar to the )e6"estC,cle* class org.apache.wicket.Session also offers support for listener entities. 2ith Session these entities must implement the callbac# interface org.apache.wicket. 2SessionListener which e,poses only the onCreated(Session session method. As you might guess from its name* this method is called when a new session is created. "ession listeners must be added to our application using a typed collection* Hust li#e we ha.e done before with reEuest cycle listeners(
!'4erride public 4oid init7:

18 http: en.wikipedia.org wiki (omposite1pattern

Wicket free user guide

38

2 @nder the hood of the re&uest processing

super.init7:1 //listener initialiPation... $)ession/istener m"/istener1 //add a custom session listener get)ession/isteners7:.add7m"/istener: &

'.#.2

Handling session attri=utes

The Session class handles session attributes in much the same way as the standard interface 5a!a(.ser!let.http.HttpSession. The following methods are pro.ided to create* read and remo.e session attributes( setAttrib"te(String name4 Seriali3able !al"e ( creates an attribute identified by the gi.en name. -f the session already contains an attribute with the same name* the new .alue will replace the e,isting one. The .alue must be a serialiCable obHect. getAttrib"te(String name ( returns the .alue of the attribute identified by the gi.en name* or n"ll if the name does not correspond to any attribute. remo!eAttrib"te(String name ( remo.es the attribute identified by the gi.en name. By default class WebSession will use the underlying http session to store attributes. 2ic#et will automatically add a prefi, to the name of the attributes. This prefi, is returned by the WebApplicationBs method getSessionAttrib"tePre0i(( .

'.#.3

Accessing to the H**P session

-f for any reason we need to directly access to the underlying HttpSession obHect* we can retrie.e it from the current reEuest with the following code(
Dttp)ession session 8 77)er4letWeb*eEuest:*eEuestC"cle.get7:.get*eEuest7:: .getContainer*eEuest7:.get)ession7:1

&sing the raw session obHect might be necessary if we ha.e to set a session attribute with a particular name without the prefi, added by 2ic#et. :etBs say for e,ample that we are wor#ing with Tomcat as web ser.er. @ne of the administrati.e tools pro.ided by Tomcat is a page listing all the acti.e user sessions of a gi.en web application(

llustration 2$1% Tomcat 'essions 7dministration page with custom values$

Wicket free user guide

5%

2 @nder the hood of the re&uest processing

Tomcat allows us to set the .alues that will be displayed in columns F0uessed localeG and F0uessed &ser nameG. @ne possible way to do this is to use session attributes named F:ocaleG and Fuser ameG but we canBt create them .ia 2ic#etBs Session class because they would not ha.e e,actly the name reEuired by Tomcat. -nstead* we must use the raw HttpSession and set our attributes on it(
Dttp)ession session 8 77)er4letWeb*eEuest:*eEuestC"cle.get7:.get*eEuest7:: .getContainer*eEuest7:.get)ession7:1 session.set5ttribute79/ocale9, 9(N-/$)D9:1 session.set5ttribute79userName9, 9;r .ad-u"9:1

'.#.#

*emporar and permanent sessions

2ic#et doesnBt need to store data into user session as long as the user .isits only stateless pages. onetheless* e.en under these conditions* a temporary session obHect is created to process each reEuest but it is discarded at the end of the current reEuest. To #now if the current session is temporary* we can use the is/emporar,( method(
)ession.get7:.isTemporar"7:1

-f a session is not temporary (i.e. it is permanent)* itBs identified by an uniEue id which can be read calling the get2d( method. This .alue will be n"ll if the session is temporary. Although 2ic#et is able to automatically recogniCe when it needs to replace a temporary session with a permanent one* sometimes we may need to manually control this process to ma#e our initially temporary session permanent. To illustrate this possible scenario letBs consider proHect 9indSession#0ample where we ha.e a stateless home page which sets a session attribute inside its constructor and then it redirects the user to another page which displays with a label the session attribute pre.iously created. The code of the two pages is as follows( 9ome page(
public class Dome#age extends Web#age public Dome#age7%inal #age#arameters parameters: )ession.get7:.set5ttribute79username9, 9tomm"9:1 )ession. get 7:.bind7:1 set*esponse#age7+ispla")ession#arameter.class:1 & &

Target page(
public class +ispla")ession#arameter extends Web#age public +ispla")ession#arameter7: super7:1 add7neC /abel79username9, 7)tring: )ession.get7:.get5ttribute79username9:::1 & &

Again* we #ept page logic .ery simple to not o.er-bloat the e,ample with unnecessary code. -n the snippet abo.e we ha.e also bolded SessionBs bind( method which con.erts temporary session into

Wicket free user guide

51

2 @nder the hood of the re&uest processing

a permanent one. -f the home page has not in.o#ed this method* the session with its attribute would ha.e been discarded at the end of the reEuest and the page :ispla,SessionParameter would ha.e displayed an empty .alue in its label.

'.#.(

5iscarding session data

@nce a user has finished using our web application* she must be able to log out and clean any session data. To be sure that a permanent session will be discarded at the end of the current reEuest* class Session pro.ides the in!alidate( method. -f we want to immediately in.alidate a gi.en session without waiting for the current reEuest to complete* we can in.o#e the in!alidateNow( method. Warning +emember that in!alidateNow( will immediately remo.e any instance of components (and pages) from the session* meaning that once we ha.e called this method we wonBt be able to wor# with them for the rest of the reEuest process.

'.( 8toring ar=itrar o=<ects with metadata


Ka.a"er.er Pages "pecification18 defines 3 scopes in which a page can create and access a .ariable. These scopes are( re%uest( .ariables declared in this scope can be seen only by pages processing the same reEuest. The lifespan of these .ariables is (at most) eEual to the one of the related reEuest. They are discarded when the full response has been generated or when the reEuest is forwarded somewhere else. pa!e( .ariables declared in this scope can be seen only by the page that has created them. session( .ariables in session scope can be created and accessed by e.ery page used in the same session where they are defined. application( this is the widest scope. Dariables declared in this scope can be used by any page of a gi.en web application. Although 2ic#et doesnBt implement the K"P "pecification (it is rather an alternati.e to it)* it offers a feature called metadata which resembles scoped .ariables but is much more powerful. <etadata is Euite similar to a Ka.a Map in that it stores pairs of #ey-.alue obHects where the #ey must be uniEue. -n 2ic#et each of the following classes has its own metadata store( )e6"estC,cle* Session* Application and Component. The #ey used for metadata is an instance of class org.apache.wicket.Meta:ata;e,7/8. To put an arbitrary obHect into metadata we must use the setMeta:ata method which ta#es two parameters as input( the #ey used to store the .alue and the .alue itself. -f we are using metadata with classes Session or Component* data obHect must be serialiCable because 2ic#et serialiCes both session and component instances. This constraint is not applied to metadata of classes Application and )e6"estC,cle which can contain a generic obHect. -n any case* the type of data obHect must be compatible with the type parameter / specified by the #ey. To retrie.e a pre.iously inserted obHect we must use the getMeta:ata(Meta:ata;e,7/8 ke, method. -n the following e,ample we set a 5a!a.s6l.Connection obHect in the applicationBs metadata so it can be used by any page of the application( Application class code(
public static ;eta+ata5pp extends Web5pplication
19 Paragraph 1$=$* :"b#ects and 'copes: of )ava'erver Pages *$1 'pecification

Wicket free user guide

54

2 @nder the hood of the re&uest processing

//+o some stu%%... /** * ;etadata ke" de%inition */ public static ;eta+ata6e"<Conncetion> connection6e" 8 neC ;eta+ata6e"<Conncetion>7: &1 /** * 5pplicationIs initialiPation */ !'4erride public 4oid init7: super.init7:1 Connection connection1 //connection initialiPation... set;eta+ata7connection6e", connection:1 //+o some other stu%%.. & &

!ode to get the obHect from the metadata(


Connection connection 8 5pplication.get7:.get;eta+ata7;eta+ata5pp.connection6e":1

"ince Meta:ata;e,7/8 class is declared as abstract* we must implement it with a subclass or with an anonymous class (li#e we did in the e,ample abo.e).

'.- 8ummar
-n this chapter we had a loo# at how 2ic#et internally handles a web reEuest. I.en if most of the time we wonBt need to customiCe this internal process* #nowing how it wor#s is essential to use the framewor# at 1%%P. Intities li#e Application and Session will come in handy again when we will tac#le the topic of security in chapter 17.

Wicket free user guide

5$

= Wicket 0inks and @A0 generation

, Wicket Links and *-L generation


&p to now we used component Link to mo.e from a page to another and we ha.e seen that it is Euiet similar to a Fclic#G e.ent handler (see paragraph 4.3). 9owe.er this component alone is not enough to build all possible #inds of lin#s we may need in our pages. Therefore* 2ic#et offers other lin# components suited for those tas#s which can not be accomplished with a basic Link. Besides learning new lin# components* in this chapter we will also see how to customiCe the page &+: generated by 2ic#et using the encoding facility pro.ided by the framewor# and the page parameters that can be passed to a target page.

2.1 PageParameters
A common practice in web de.elopment is to pass data to a page using 5uery string parameters (li#e ? paramName1=paramValu1&paramName2=paramValue2...). 2ic#et offers a more fle,ible and obHect oriented way to do this with models (we will see them in the ne,t chapter). 9owe.er* e.en if we are using 2ic#et* we still need to use Euery string parameters to e,change data with other -nternet-based ser.ices. !onsider for e,ample a classic confirmation page which is lin#ed inside an email to let users confirm important actions li#e password changing or the subscription to a mailing list. This #ind of page usually e,pects to recei.e a Euery string parameter containing the id of the action to confirm. Query string parameters can also be referred to as named parameters. -n 2ic#et they are handled with class org.apache.wicket.re6"est.mapper.parameter.PageParameters. "ince named parameters are basically name-.alue pairs* PageParameters wor#s in much the same way as Ka.a Map pro.iding two methods to create/modify a parameter ( add(String name4 +b5ect !al"e and set(String name4 +b5ect !al"e )* one method to remo.e an e,isting parameter (remo!e(String name ) and one to retrie.e the .alue of a gi.en parameter ( get(String name ) . 9ere is a snippet to illustrate the usage of PageParameters(
#age#arameters page#arameters 8 neC #age#arameters7:1 //add a couple o% parameters page#arameters.add79name9, 9Lohn9:1 page#arameters.add79age9, =B:1 //retrie4e the 4alue o% IageI parameter page#arameters.get79age9:1

ow that we ha.e seen how to wor# with page parameters* letBs see how to use them with our pages.

2.1.1

PageParameters and =ookmarka=le pages

Base class Page comes with a constructor which ta#es as input a PageParameters instance. -f we use this superclass constructor in our page* PageParameters will be used to build the page &+: and it can be retrie.ed at a later time with the PageBs getPageParameters( method. -n the following e,ample ta#en from the PageParameters#0ample proHect we ha.e a home page with a lin# to a second page that uses a .ersion of set)esponsePage method that ta#es as input also a PageParameters to build the target page (named PageWithParameters). The code for the lin# and for the target page is the following(
Wicket free user guide

53

= Wicket 0inks and @A0 generation

:in# code(
add7neC /ink79pageWith$ndex#aram9: !'4erride public 4oid onClick7: #age#arameters page#arameters 8 neC #age#arameters7:1 page#arameters.add79%oo9, 9%oo9:1 page#arameters.add79bar9, 9bar9:1 set*esponse#age7#ageWith#arameters.class, page#arameters:1 & &:1

Target page code(


public class #ageWith#arameters extends Web#age //'4erride superclass constructor public #ageWith#arameters7#age#arameters parameters: super7parameters:1 & &

The code is Euite straightforward and itRs more interesting to loo# at the &+: generated for the target page(
<app root>/#age#arameters(xample/Cicket/bookmarkable/org.CicketTutorial.#ageWith#arameters ?%oo8%ooUbar8bar

At first glance the &+: abo.e could seem a little weird* e,cept for the last part which contains the two named parameters used to build the target page. The reason for this FstrangeG &+: is that* as we e,plained in paragraph A.4.5* when a page is instantiated using a constructor with no argument or using a constructor that accepts only a PageParameters* 2ic#et will try to generate a static &+: for it* with no session-relati.e informations. This #ind of &+: is called bookmarkable because it can be sa.ed by the users as a boo#mar# and accessed at a later time. A boo#mar#able &+: is composed by a fi,ed prefi, (which by default is bookmarkable) and the Eualified name of the page class ( org.wicket/"torial.PageWithParameters in our e,ample). "egment Cicket is another fi,ed prefi, added by default during &+: generation. -n paragraph 7.A.3 we will see how to customiCe fi,ed prefi,es with a custom implementation of 2MapperConte(t interface.

2.1.2

!ndexed parameters

Besides named parameters* 2ic#et also supports inde0ed parameters. These #inds of parameters are rendered as &+: segments placed before named parameters. :etBs consider for e,ample the following &+:(
<application path>/%oo/bar?@UbaP8baP

The &+: abo.e contains two inde,ed parameters ( %oo and bar) and a Euery string consisting of the page id and a named parameter (baP). Kust li#e named parameters also inde,ed parameters are

Wicket free user guide

55

= Wicket 0inks and @A0 generation

handled by the PageParameters class. The methods pro.ided by PageParameters for inde,ed parameters are set(int inde(4 +b5ect ob5ect (to add/modify a parameter)* remo!e(int inde( (to remo.e a parameter) and get(int inde( (to read a parameter). As their name suggests* inde,ed parameters are identified by a numeric inde, and they are rendered following the order in which they ha.e been added to the PageParameters. The following is an e,ample of inde,ed parameters(
#age#arameters page#arameters 8 neC #age#arameters7:1 //add a couple o% parameters page#arameters.set7A, 9%oo9:1 page#arameters.set7@, 9bar9:1 //retrie4e the 4alue o% the second parameter 79bar9: page#arameters.get7@:1

ProHect PageParameters#0ample comes also with a lin# to a page with both inde,ed parameters and a named parameter(
add7neC /ink79pageWithNamed$ndex#aram9: !'4erride public 4oid onClick7: #age#arameters page#arameters 8 neC #age#arameters7:1 page#arameters.set7A, 9%oo9:1 page#arameters.set7@, 9bar9:1 page#arameters.add79baP9, 9baP9:1 set*esponse#age7#ageWith#arameters.class, page#arameters:1 & &:1

The &+: generated for the lin#ed page (PageWithParameters) is the one seen at the beginning of the paragraph.

2.2 ;ookmarka=le links


A lin# to a boo#mar#able page can be built with the lin# component org.apache.wicket.mark"p. html.link.1ookmarkablePageLink(
.ookmarkable#age/ink bpl8neC .ookmarkable#age/ink7#ageWith#arameters.class, page#arameters:1

The specific purpose of this component is to pro.ide an anchor to a boo#mar#able page* hence we donBt ha.e to implement any abstract method li#e we do with Link component.

2.3 Automaticall creating =ookmarka=le links with tag Kwicket:linkL


Boo#mar#able pages can be lin#ed directly inside mar#up files without writing any Ka.a code. &sing tag we as# 2ic#et to automatically add boo#mar#able lin#s for the anchors wrapped inside it. 9ere is an e,ample of usage of <Cicket:link> tag ta#en from the home page of the proHect 9ookmarkablePage$uto%ink(
<Cicket:link>

Wicket free user guide

5A

= Wicket 0inks and @A0 generation

<F+'CTG#( html> <html xmlns:Cicket89http://Cicket.apache.org9> <head> <meta charset89ut%-B9 /> <title>5pache Wicket Vuickstart</title> </head> <bod"> <di4 id89bd9> <Cicket:link> <a hre%89Dome#age.html9>Dome#age</a><br/> <a hre%89another#ackage/)ub#ackage#age.html9>)ub#ackage#age</a> </Cicket:link> </di4> </bod"> </html>

The #ey part of the mar#up abo.e is the hre% attribute which must contain the pac#age-relati.e path to a page. The home page is inside pac#age org.wicket/"torial which in turns contains the sub pac#age anotherPackage. This pac#age hierarchy is reflected by the hre% attributes( in the first anchor we ha.e a lin# to the home page itself while the second anchor points to page S"bPackagePage which is placed into sub pac#age anotherPackage. Absolute paths are supported as well and we can use them if we want to specify the full pac#age of a gi.en page. =or e,ample the lin# to S"bPackagePage could ha.e been written in the following (more .erbose) way (
<a hre%89/org/CicketTutorial/another#ackage/)ub#ackage#age.html9>)ub#ackage#age</a>

-f we ta#e a loo# also at the mar#up of S"bPackagePage we can see that it contains a lin# to the home page which uses the parent directory selector (relati.e path)(
<F+'CTG#( html> <html xmlns:Cicket89http://Cicket.apache.org9> <head> <meta charset89ut%-B9 /> <title>5pache Wicket Vuickstart</title> </head> <bod"> <di4 id89bd9> <Cicket:link> <a hre%89../Dome#age.html9>Dome#age</a><br/> <a hre%89)ub#ackage#age.html9>)ub#ackage#age</a> </Cicket:link> </di4> </bod"> </html>

Please note that any lin# to the current page (a#a self link) is disabled. =or e,ample in the home page the self lin# is rendered li#e this(
<span><em>Dome#age</em></span

Wicket free user guide

56

= Wicket 0inks and @A0 generation

The mar#up used to render disabled lin#s can be customiCed using the mar#up settings (interface 2Mark"pSettings) a.ailable in the application class(
!'4erride public 4oid init7: super.init7:1 //Crap disabled links Cith <b> tag get;arkup)ettings7:.set+e%ault.e%ore+isabled/ink79<b>9:1 get;arkup)ettings7:.set+e%ault5%ter+isabled/ink79</b>9:1 &

The purpose of <Cicket:link> tag is not limited to Hust simplifying the usage of boo#mar#able pages. As we we will see in chapter 1$* this tag can also be adopted to manage web resources li#e pictures* !"" files* Ka.a"cript files and so on.

2.# Dxternal links


"ince 2ic#et uses plain 9T<: mar#up files as templates* we can place an anchor to an e,ternal page directly inside the mar#up file. 2hen we need to dynamically generate e,ternal anchors* we can use lin# component org.apache.wicket.mark"p.html.link.'(ternalLink. -n order to build an e,ternal lin# we must specify the .alue of the hre% attribute using a model or a plain string. -n the ne,t snippet* gi.en an instance of Person* we generate a 0oogle search Euery for its full name( 9tml(
<a Cicket:id89external)ite9>)earch me on -oogleF</a>

Ka.a code(
#erson person 8 neC #erson79Lohn9, 9)mith9:1 )tring %ullName 8 person.get3ullName7:1 //)pace characters must be replaced b" character I>I )tring googleVuer" 8 9http://CCC.google.com/search?E89 > %ullName.replace79 9, 9>9:1 add7neC (xternal/ink79external)ite9, googleVuer"::1

0enerated anchor(
<a hre%89http://CCC.google.com/search?E8Lohn>)mith9>)earch me on -oogleF</a>

-f we need to specify a dynamic .alue for the te,t inside the anchor* we can pass it as an additional constructor parameter( 9tml(
<a Cicket:id89external)ite9>/abel goes here...</a>

Ka.a code(
#erson person 8 neC #erson79Lohn9, 9)mith9:1 )tring %ullName 8 person.get3ullName7:1 )tring googleVuer" 8 9http://CCC.google.com/search?E89 > %ullName.replace79 9, 9>9:1 )tring link/abel 8 9)earch I9 > %ullName > 9I on -oogle.91 add7neC (xternal/ink79external)ite9, googleVuer", link/abel::1

Wicket free user guide

57

= Wicket 0inks and @A0 generation

0enerated anchor(
<a hre%89http://CCC.google.com/search?E8Lohn>)mith9>)earch ILohn )mithI on -oogle.</a>

2.( 8tateless links


!omponent Link has a stateful nature* hence it cannot be used with stateless pages. To use lin#s with these #inds of pages 2ic#et pro.ides the con.enience org.apache.wicket.mark"p.html. link.StatelessLink component which is basically a subtype of Link with the stateless hint set to true. Please #eep in mind that 2ic#et generates a new instance of a stateless page also to ser.e stateless lin#s* so the code inside the onClick( method can not depend on instance .ariables. To illustrate this potential issue letBs consider the following code (from the proHect StatelessPage) where the .alue of the .ariable inde( is used inside onclick( (
public class )tateless#age extends Web#age pri4ate int index 8 A1 public )tateless#age7#age#arameters parameters: super7parameters:1 & !'4erride protected 4oid on$nitialiPe7: super.on$nitialiPe7:1 set)tatelessDint7true:1 add7neC )tateless/ink79stateless/ink9: !'4erride public 4oid onClick7: //$t Cill alCa"s print Pero )"stem.out.println7index>>:1 & &:1 & &

The printed .alue will always be Cero because a new instance of the page is used e.ery time the user clic#s on the statelessLink lin#.

2.- Generating structured and clear 03,s


9a.ing structured &+:s in our site is a basic reEuirement if we want to build an efficient "I@ 4% strategy* but it also contributes to impro.e user e,perience with more intuiti.e &+:s. 2ic#et pro.ides two different ways to control &+: generation. The first (and simplest) is to FmountG one or more pages to an arbitrary path* while a more powerful techniEue is to use custom implementations of 2MapperConte(t and 2PageParameters'ncoder interfaces. -n the ne,t paragraphs we will learn both of these two techniEues.

20 http%CCen$wikipedia$orgCwikiC'earchDengineDoptimi<ation

Wicket free user guide

58

= Wicket 0inks and @A0 generation

2.-.1

+ounting a single page

2ith 2ic#et we can mount a page to a gi.en path in much the same way as we map a ser.let filer to a desired path inside file web.0ml (see page 8). &sing mo"ntPage(String path4 Class 7/8 pageClass method of the WepApplication class we tell 2ic#et to respond with a new instance of pageClass whene.er a user na.igates to the gi.en path. -n the application class of the proHect 4ountedPages#0ample we mount Mo"ntedPage to the 9<pageMo"nt= path(
!'4erride public 4oid init7: super.init7:1 mount#age79/page;ount9, ;ounted#age.class:1 //'ther initialiPation code... &

The path pro.ided to mo"ntPage will be used to generate the &+: for any page of the specified class(
//it Cill return 9/page;ount9 *eEuestC"cle.get7:.url3or7;ounted#age.class:1

&nder the hood the mo"ntPage method mounts an instance of the reEuest mapper org.apache. wicket.re6"est.mapper.Mo"ntedMapper configured for the gi.en path(
public %inal <T extends #age> 4oid mount#age7%inal )tring path,%inal Class<T> pageClass: mount7neC ;ounted;apper7path, pageClass::1 &

+eEuest mappers and the ApplicationBs method chapter (paragraph 6.$.1). 2.-.2

mount

ha.e been introduced in the pre.ious

0sing parameter placeholders with mounted pages

The path specified for mounted pages can contain dynamic segments which are populated with the .alues of the named parameters used to build the page. These segments are declared using special segments called parameter placeholders. !onsider the path used in the following e,ample(
mount#age79/page;ount/W %oo&/other)egm9, ;ounted#ageWith#laceholder.class:1

The path used abo.e is composed by three segments( the first and the last are fi,ed while the second will be replaced by the .alue of the named parameter %oo that must be pro.ided when the page Mo"ntedPageWithPlaceholder is instantiated(

Ka.a code(
#age#arameters page#arameters 8 neC #age#arameters7:1 page#arameters.add79%oo9, 9%oo9:1 set*esponse#age7;ounted#ageWith#laceholder.class, page#arameters:1

Wicket free user guide

A%

= Wicket 0inks and @A0 generation

0enerated &+:(
<5pplication path>/page;ount/%oo/other)egm

@n the contrary if we manually insert an &+: li#e B <Ceb app path>/page;ount/bar/other)egmI* we can read .alue BbarB retrie.ing the named parameter %oo inside our page. Place holders can be declared as optional using the BSB character in place of BTB(
mount#age79/page;ount/X %oo&/other)egm9, ;ounted#age'ptional#laceholder.class:1

-f the named parameter for an optional placeholder is missing* the corresponding segment is remo.ed from the final &+:(

Ka.a code(
#age#arameters page#arameters 8 neC #age#arameters7:1 set*esponse#age7;ounted#ageWith#laceholder.class, page#arameters:1

0enerated &+:(
<5pplication path>/page;ount/other)egm

2.-.3

+ounting a package

-n addition to mounting a single page* 2ic#et allows to mount all of the pages inside a pac#age to a gi.en path. <ethod mo"ntPackage(String path4 Class7/8 pageClass of class WepApplication will mount e.ery page inside pageClassBs pac#age to the specified path. The resulting &+: for pac#age-mounted pages will ha.e the following structure(
<5pplication path>/mounted#ath/<#ageClassName>Hoptional Euer" stringJ

=or e,ample in the 4ountedPages#0ample proHect we ha.e mounted all pages inside the subpac#age org.t"torialWicket.s"bPackage with this line of code(
mount#ackage79/mount#ackage9, )tate%ul#ackage;ount.class:1

State0"lPackageMo"nt is one of the pages placed into the desired pac#age and its &+: will be(
<5pplication path>/mount#ackage/)tate%ul#ackage;ount?@

"imilarly to what is done by the mo"ntPage method* the implementation of the mo"ntPackage method mounts an instance of org.apache.wicket.re6"est.mapper.PackageMapper to the gi.en path.

2.-.#

Providing custom mapper conte(t to re1uest mappers

-nterface org.apache.wicket.re6"est.mapper.2MapperConte(t is used by reEuest mappers to create new page instances and to retrie.e static &+: segments used to build and parse page &+:s. 9ere is the list of these segments( )amespace( itBs the first &+: segment of not-mounted pages. By default its .alue is Cicket. Identifier for non bookmarkable :"%s ( itBs the segment that identifies non boo#mar#able pages.
Wicket free user guide

A1

= Wicket 0inks and @A0 generation

By default its .alue is page. Identifier for bookmarkable :"%s( itBs the segment that identifies boo#mar#able pages. By default its .alue is bookmarkable (as we ha.e seen before in paragraph 7.1.1). Identifier for resources( itBs the segment that identifies 2ic#et resources. -ts default .alue is resources. The topic of resource management will be co.ered in chapter 1$.

2MapperConte(t pro.ides a getter method for any segment listed abo.e. By default 2ic#et uses class org.apache.wicket.:e0a"ltMapperConte(t as mapper conte,t. ProHect (ustom4apper(onte0t is an e,ample of customiCation of mapper conte,t where we use index as identifier for non-boo#mar#able pages and static0*/ as identifier for boo#mar#able pages. -n this proHect* instead of implementing our mapper conte,t from scratch* we used :e0a"ltMapperConte(t as base class o.erriding Hust the two methods we need to achie.e the desired result (get1ookmarkable2denti0ier( and getPage2denti0ier( ). The final implementation is the following(
public class Custom;apperContext extends +e%ault;apperContext !'4erride public )tring get.ookmarkable$denti%ier7: return 9static0*/91 & !'4erride public )tring get#age$denti%ier7: return 9index91 & &

ow to use a custom mapper conte,t in our application we must o.erride the newMapperConte(t( method declared in the Application class and ma#e it return our custom implementation of 2MapperConte(t(
!'4erride protected $;apperContext neC;apperContext7: return neC Custom;apperContext7:1 &

2.-.(

.ontrolling how page parameters are encoded with !PageParametersDncoder

"ome reEuest mappers (li#e Mo"ntedMapper and PackageMapper) can delegate page parameters encoding/decoding to interface org.apache.wicket.re6"est.mapper.parameter.2Page Parameters'ncoder. This entity e,poses two methods( encodePageParameters( and decodePageParameters( ( the first one is in.o#ed to encode page parameters into an &+: while the second one e,tracts parameters from the &+:. 2ic#et comes with a built-in implementation of this interface which encodes named page parameters as &+: segments using the following patter( /paramName1/paramValue1/paramName2/param Value2... This built-in encoder is org.apache.wicket.re6"est.mapper.parameter.UrlPathPage ParametersEncoder class. -n the PageParameters#ncoder#0ample proHect we ha.e manually mounted a Mo"ntedMapper that ta#es as input also an 9rlPathPageParameters'ncoder(
!'4erride

Wicket free user guide

A4

= Wicket 0inks and @A0 generation

public 4oid init7: super.init7:1 mount7neC ;ounted;apper79/mounted#ath9, ;ounted#age.class, neC 0rl#ath#age#arameters(ncoder7:::1 &

The home page of the proHect contains Hust a lin# to the Mo"ntedPage web page. The code of the lin# and the resulting page &+: are(

:in# code(
add7neC /ink79mounted#age9: !'4erride public 4oid onClick7: #age#arameters page#arameters 8 neC #age#arameters7:1 page#arameters.add79%oo9, 9%oo9:1 page#arameters.add79bar9, 9bar9:1 set*esponse#age7;ounted#age.class, page#arameters:1 & &:1

0enerated &+:(
<5pplication path>/mounted#ath/%oo/%oo/bar/bar?@

2.-.-

Dncr pting page 03,s

"ometimes &+:s are a doubleUedged sword for our site because they can e,pose too many details about the internal structure of our web application and malicious users could e,ploit them to perform a cross-site reEuest forgery41. To a.oid this #ind of security threat we can use the Cr,ptoMapper reEuest mapper which wraps an e,isting mapper and encrypts the original &+: producing a single encrypted segment(

llustration =$1% 7n @A0 with the encrypted segment Typically* Cr,ptoMapper is registered into a 2ic#et application as the root reEuest mapper wrapping the default one(
!'4erride public 4oid init7: super.init7:1 set*oot*eEuest;apper7neC Cr"pto;apper7get*oot*eEuest;apper7:, this::1 //pages and resources must be mounted a%ter Ce ha4e set Cr"pto;apper mount#age79/%oo/9, Dome#age.class:1

21 http: en.wikipedia.org wiki (ross*site1re5uest1forgery

Wicket free user guide

A$

= Wicket 0inks and @A0 generation

&

As pointed out in the code abo.e* pages and resources must be mounted after ha.ing set Cr,ptoMapper as root mapper* otherwise the mounted paths will not wor#.

2.' 8ummar
:in#s and &+:s are not tri.ial topics as they may seem and in 2ic#et they are strictly interconnected. De.elopers must choose the right trade-off between producing structured &+:s and a.oiding to ma#e them .erbose and .ulnerable. -n this chapter we ha.e e,plored the tools pro.ided by 2ic#et to control how &+:s are generated. 2e ha.e started with static &+:s for boo#mar#able pages and we ha.e seen how to pass parameters to target pages with PageParameters. -n the second part of the chapter we focused on mounting pages to a specific path and on controlling how parameters are encoded by 2ic#et. =inally* we ha.e also seen how to encrypt &+:s to pre.ent security .ulnerabilities.

Wicket free user guide

A3

> Wicket models and forms

. Wicket models and forms


-n 2ic#et the concept of FmodelG 44 is probably the most important topic of the entire framewor# and it is strictly related to the usage of its components. -n addition* models are also an important element for internationaliCation* as we will see in paragraph 14.A. 9owe.er* despite their fundamental role* in 2ic#et models are not difficult to understand but the best way to learn how they wor# is to use them with forms. ThatBs why we ha.enBt tal#ed about models so far* and why this chapter discusses these two topics together.

4.1 What is a model"


<odel is essentially a facade4$ interface which allows components to access and modify their data without #nowing any detail about how they are managed or persisted. I.ery component has at most one related model* while a model can be shared among different components. -n 2ic#et a model is any implementation of the interface org.apache.wicket.model.2Model(

llustration >$1% @/0 class diagram of Component and /odel The 2Model interface defines Hust the methods needed to get and set a data obHect ( get+b5ect( and set+b5ect( )* decoupling components from concrete details about the persistence strategy adopted for data. -n addition* the le.el of indirection introduced by models allows access data obHect only when it is really needed (for e,ample during the rendering phase) and not earlier when it may not be ready to be used. Any component can get/set its model as well as its data obHect using the 3 public shortcut methods listed in the class diagram abo.e. The two methods onModelChanged( and onModelChanging( are triggered by 2ic#et each time a model is modified( the first one is called after the model has been changed* the second one Hust before the change occurs. -n the e,amples seen so far we ha.e wor#ed with Label component using its constructor which ta#es as input two string parameters* the component id and the te,t to display(
add7neC /abel79hello;essage9, 9Dello WicketWorldF9::1

This constructor internally builds a model which wraps the second string parameter. ThatBs why we didnBt mention label model in the pre.ious e,amples. 9ere is the code of this constructor(
public /abel7%inal )tring id, )tring label:
22 Wicket models have nothing to do with the model we talked about in paragraph 1$*,, 23 (or an introduction to (acade pattern see http: en.wikipedia.org wiki ;acade1pattern

Wicket free user guide

A5

> Wicket models and forms

this7id, neC ;odel<)tring>7label::1 &

!lass org.apache.wicket.model.Model is a basic implementation of 2Model. -t can wrap any obHect that implements the interface 5a!a.io.Seriali3able. The reason of this constraint o.er data obHect is that this model is stored in the web session* and we #now from chapter A that data are stored into session using serialiCation. >ote -n general* 2ic#et models support a detaching capability that allows us to wor# also with non-serialiCable obHects as data model. 2e will see the detaching mechanism later in this chapter. Kust li#e any other 2ic#et components* Label pro.ides a constructor that ta#es as input the component id and the model to use with the component. &sing this constructor the pre.ious e,ample becomes(
add7neC /abel79hello;essage9, neC ;odel<)tring>79Dello WicketWorldF9:::1

>ote The Model class comes with a bunch of factory methods that ma#es it easier to build new model instances. =or e,ample the o0(/ ob5ect method creates a new instance of Model which wraps any +b5ect instance inside it. "o instead of writing
neC ;odel<)tring>79Dello WicketWorldF9:

we can write
;odel.o%79Dello WicketWorldF9:

-f the data obHect is a List* a Map or a Set we can use similar methods called o0List* o0Map and o0Set. =rom now on we will use these factory methods in our e,amples. -tBs Euite clear that if our Label must display a static te,t it doesnBt ma#e much sense to build a model by hand li#e we did in the last code e,ample. 9owe.er is not unusual to ha.e a Label that must display a dynamic .alue* li#e the input pro.ided by a user or a .alue read from a database. 2ic#et models are designed to sol.e these #inds of problems. :etBs say we need a label to display the current time stamp each time a page is rendered. 2e can implement a custom model which returns a new :ate instance when the get+b5ect( method is called(
$;odel time)tamp;odel 8 neC ;odel<)tring>7: !'4erride public )tring get'b2ect7: return neC +ate7:.to)tring7:1 & &1

Wicket free user guide

AA

> Wicket models and forms

add7neC /abel79time)tamp9, time)tamp;odel::1

I.en if sometimes writing a custom model could be a good choice to sol.e a specific problem* 2ic#et already pro.ides a set of 2Model implementations which should fit most of our needs. -n the ne,t paragraph we will see a couple of models that allow us to easily integrate Ka.aBeans with our web applications and in particular with our forms. >ote By default class Component escapes 9T<: sensiti.e characters (li#e B 7B* B8B or B>B) from the te,tual representation of its model obHect. The term BescapeB means that these characters will be replaced with their corresponding 9T<: entity 43 (for e,ample B7B becomes B>lt? B). This is done for security reasons as a malicious user could attempt to inHect mar#up or Ka.a"cript into our pages. -f we want to display the raw content stored inside a model* we can tell the Component class not to escape characters by calling the set'scape ModelStrings(0alse method.

4.2 +odels and 7ava;eans


@ne of the main goals of 2ic#et is to use Ka.aBeans and P@K@ as data model* o.ercoming the impedance mismatch between web technologies and @@ paradigm. -n order to ma#e this tas# as easy as possible* 2ic#et offers two special model classes( org.apache.wicket.model.Propert,Model and org.apache.wicket.model.Compo"ndPropert,Model. 2e will see how to use them in the ne,t two e,amples* using the following Ka.aBean as the data obHect(
public class #erson implements )erialiPable pri4ate )tring name1 pri4ate )tring surname1 pri4ate )tring address1 pri4ate )tring email1 pri4ate )tring passportCode1 pri4ate #erson spouse1 pri4ate /ist<#erson> children1 public #erson7)tring name, )tring surname: this.name 8 name1 this.surname 8 surname1 & public )tring get3ullName7: return name > 9 9 > surname1 & /* -etters and setters %or pri4ate %ields ... */
24 http: en.wikipedia.org wiki (haracter1entity1reference

Wicket free user guide

A6

> Wicket models and forms

&

4.2.1

Propert +odel

:etBs say we want to display the name field of a Person instance with a label. 2e could* of course* use the Model class li#e we did in the pre.ious e,ample* obtaining something li#e this(
#erson person 8 neC #erson7:1 //load personIs data... /abel label 8 neC /abel79name9, neC ;odel7person.getName7:::1

9owe.er this solution has a huge drawbac#( the te,t displayed by the label will be static and if we change the .alue of the field* the label wonBt update its content. -nstead* to always display the current .alue of a class field* we should use the org.apache.wicket.model.Propert,Model model class(
#erson person 8 neC #erson7:1 //load personIs data... /abel label 8 neC /abel79name9, neC #ropert";odel7person, 9name9::1

Propert,Model has Hust one constructor with two parameters( the model obHect ( person in our e,ample) and the name of the property we want to read/write ( 9name9 in our e,ample). This last parameter is called property e0pression. -nternally* methods get2b-ect/set2b-ect use property e,pression to get/set propertyBs .alue. To resol.e class properties Propert,Model uses class org.apache.wicket."til.lang.Propert, )esol!er which can access any #ind of property* pri.ate fields included. Kust li#e Ka.a language* property e,pressions support dotted notation to select sub properties. "o if we want to display the name of the PersonBs spouse we can write(
/abel label 8 neC /abel79spouseName9, neC #ropert";odel7person, 9spouse.name9::1

>ote Propert,Model is null-safe* which means we donBt ha.e to worry if property e,pression includes a null .alue in its path. -f such a .alue is encountered* an empty string will be returned. -f property is an array or a List* we can specify an inde, after its name. =or e,ample* to display the name of the first child of a Person we can write the following property e,pression(
/abel label 8 neC /abel79%irstChildName9, neC #ropert";odel7person, 9children.A.name9::1

-nde,es and map #eyes can be also specified using sEuared brac#ets li#e FchildrenV%W.nameG or Fmap=ieldV#eyW.subfieldG.

4.2.2

.ompoundPropert +odel and model inheritance

!lass org.apache.wicket.model.Compo"ndPropert,Model is a particular #ind of model which is usually used in conHunction with another 2ic#et feature called model inheritance. 2ith this feature* when a component needs to use a model but no one has been assigned to it* it will

Wicket free user guide

A7

> Wicket models and forms

search through the whole container hierarchy for a parent with an inheritable model. -nheritable models are those which implement interface org.apache.wicket.model.2Component2nheritedModel and Compo"ndPropert,Model is one of them. @nce a Compo"ndPropert,Model has been inherited by a component* it will beha.e Hust li#e a Propert,Model using the id of the component as property e,pression. As a conseEuence* to ma#e the most of Compo"ndPropert,Model we must assign it to one of the container of a gi.en component* rather than directly to the component itself. =or e,ample if we use Compo"ndPropert,Model with the pre.ious e,ample (display spouseBs name)* the code would become li#e this(
//set Compound#ropert";odel as model %or the container o% the label set+e%ault;odel7neC Compound#ropert";odel7person::1 /abel label 8 neC /abel79spouse.name9:1 add7label:1

ote that now the id of the label is eEual to the property e,pression pre.iously used with Propert,Model. ow as a further e,ample letBs say we want to e,tend the code abo.e to display all of the main informations of a person (name* surname* address and email). All we ha.e to do is to add one label for e.ery additional information using the relati.e property e,pression as component id(
//Create a person named ILohn )mithI #erson person 8 neC #erson79Lohn9, 9)mith9:1 set+e%ault;odel7neC Compound#ropert";odel7person::1 add7neC /abel79name9::1 add7neC /abel79surname9::1 add7neC /abel79address9::1 add7neC /abel79email9::1 add7neC /abel79spouse.name9::1

Compo"ndPropert,Model can sa.e us a lot of boring coding if we choose the id of components according to properties name. 9owe.er itBs also possible to use this type of model e.en if the id of a component does not correspond to a .alid property e,pression. The method bind(String propert, allows to create a property model from a gi.en Compo"ndPropert,Model using the pro.ided parameter as property e,pression. =or e,ample if we want to display the spouseBs name in a label ha.ing 9x"P9 as id* we can write the following code(
//Create a person named ILohn )mithI #erson person 8 neC #erson79Lohn9, 9)mith9:1 Compound#ropert";odel compound;odel1 set+e%ault;odel7compound;odel 8 neC Compound#ropert";odel7person::1 add7neC /abel79x"P9, compound;odel.bind79spouse.name9:::1

Compo"ndPropert,Model are particularly useful when used in combination with 2ic#et forms* as we will see in the ne,t paragraph.

Wicket free user guide

A8

> Wicket models and forms

>ote Model is referred to as static model because the result of its method get+b5ect is fi,ed an it is not dynamically e.aluated each time the method is called. -n contrast* models li#e Propert,Model and Compo"ndPropert, Model are called dynamic models.

4.3 Wicket forms


2eb applications use 9T<: forms to collect user input and send it to the ser.er. 2ic#et pro.ides org.apache.wicket.mark"p.html.0orm.Form class to handle web forms. This component must be bound to <%orm> tag. The following snippet shows how to create a .ery basic 2ic#et form in a page( 9tml(
<%orm Cicket:id89%orm9> <input t"pe89submit9 4alue89submit9/> </%orm>

Ka.a code(
3orm %orm 8 neC 3orm79%orm9: !'4erride protected 4oid on)ubmit7: )"stem.out.println793orm submitted.9:1 & &1 add7%orm:1

<ethod onS"bmit is called whene.er a form has been submitted and it can be o.erridden to perform custom actions. Please note that a 2ic#et form can be submitted using a standard 9T<: submit button which is not mapped to any component (i.e. it does not ha.e a Cicket:id attribute). -n the ne,t chapter we will continue to e,plore 2ic#et forms and we will see how to submit forms using special components which implement interface org.apache.wicket.mark"p.html.0orm. 2FormS"bmitter.

4.3.1

Horm and models

A form should contain some input fields (li#e te,t fields* chec# bo,es* radio buttons* drop-dpwn lists* te,t areas* etc...) to interact with users. 2ic#et pro.ides an abstraction for all these #inds of elements with component org.apache.wicket.mark"p.html.0orm.FormComponent(

llustration >$*% (ormComponent and some of the most common input components$ 7ll classes are under package org$apache$wicket$markup$html$form$

Wicket free user guide

6%

> Wicket models and forms

The purpose of FormComponent is to store the corresponding user input into its model when the form is submitted. The form is responsible for mapping input .alues to the corresponding components* a.oiding us the burden of manually synchroniCing models with input fields and .ice .ersa.

4.3.2

,ogin form

As first e,ample of interaction between the form and its models* we will build a classic login form which as#s for username and password (proHect %ogin;orm). Warning The topic of security will be discussed later in chapter 17. The following form is for e,ample purposes only and is not suited for a real application. -f you need to use a login form you should consider to use component org.apache.wicket.a"throles.a"thentication.panel.Sign2nPanel shipped with 2ic#et. This form needs two te,t fields* one of which must be a password field. 2e should also use a label to display the result of login process45. =or the sa#e of simplicity* the login logic is all inside onS"bmit and is Euite tri.ial. The following is a possible implementation of our form(
public class /ogin3orm extends 3orm pri4ate Text3ield username3ield1 pri4ate #assCordText3ield passCord3ield1 pri4ate /abel login)tatus1 public /ogin3orm7)tring id: super7id:1 username3ield 8 neC Text3ield79username9, ;odel.o%799::1 passCord3ield 8 neC #assCordText3ield79passCord9, ;odel.o%799::1 login)tatus 8 neC /abel79login)tatus9, ;odel.o%799::1 add7username3ield:1 add7passCord3ield:1 add7login)tatus:1 & public %inal 4oid on)ubmit7: )tring username 8 7)tring:username3ield.get+e%ault;odel'b2ect7:1 )tring passCord 8 7)tring:passCord3ield.get+e%ault;odel'b2ect7:1 i%7username.eEuals79test9: UU passCord.eEuals79test9:: login)tatus.set+e%ault;odel'b2ect79CongratulationsF9:1 else login)tatus.set+e%ault;odel'b2ect79Wrong username or passCordF9:1 & &

-nside formBs constructor we build the three components used in the form and we assign them a model containing an empty string(
25 n chapter 1E we will see that Wicket offers a builtFin mechanism to display feedback messages to user$

Wicket free user guide

61

> Wicket models and forms

username3ield 8 neC Text3ield79username9, ;odel.o%799::1 passCord3ield 8 neC #assCordText3ield79passCord9, ;odel.o%799::1 login)tatus 8 neC /abel79login)tatus9, ;odel.o%799::1

-f we donBt pro.ide a model to a form component* we will get the following e,ception on form submission(
2a4a.lang.$llegal)tate(xception: 5ttempt to set model ob2ect on null model o% component:

!omponent /e(tField corresponds to the standard te,t field* without any particular beha.ior or restriction on the allowed .alues. 2e must bind this component to the <input> tag with the attribute t"pe set to 9text9. Password/e(tField is a subtype of /e(tFiled and it must be used with an <input> tag with the attribute t"pe set to9passCord9. =or security reasons component Password/e(tField cleans its .alue at each reEuest* so it wil be always empty after the form has been rendered. By default Password/e(tField fields are re5uired, meaning that if we left them empty* the form wonBt be submitted (i.e. onS"bmit wonBt be called). !lass FormComponent pro.ides method set)e6"ired(boolean re6"ired to change this beha.ior. 4A -nside onS"bmit, to get/set model obHects we ha.e used shortcut methods set:e0a"ltModel+b5ect and get:e0a"ltModel+b5ect. Both methods are defined in class Component (see class diagram from -llustration 8.1). The following are the possible mar#up and code for the login page( 9tml(
<html> <head> <title>/ogin page</title> </head> <bod"> <%orm id89login3orm9 method89get9 Cicket:id89login3orm9> <%ieldset> <legend st"le89color: X3SA9>/ogin</legend> <p Cicket:id89login)tatus9></p> <span >0sername: </span><input Cicket:id89username9 t"pe89text9 id89username9 /><br/> <span >#assCord: </span><input Cicket:id89passCord9 t"pe89passCord9 id89passCord9 /> <p> <input t"pe89submit9 name89/ogin9 4alue89/ogin9/> </p> </%ieldset> </%orm> </bod"> </html>

Ka.a code(
public class Dome#age extends Web#age public Dome#age7%inal #age#arameters parameters:
26 Chapter 1E will cover form validation in detail$

Wicket free user guide

64

> Wicket models and forms

super7parameters:1 add7neC /ogin3orm79login3orm9::1 & &

The e,ample shows how 2ic#et form components can be used to store user input inside their model. 9owe.er we can dramatically impro.e the form code using Compo"ndPropert,Model and its ability to access the properties of its model obHect. The re.isited code is the following (the %ogin;orm"evisited proHect)(
public class /ogin3orm extends 3orm pri4ate )tring username1 pri4ate )tring passCord1 pri4ate )tring login)tatus1 public /ogin3orm7)tring id: super7id:1 set+e%ault;odel7neC Compound#ropert";odel7this::1 add7neC Text3ield79username9::1 add7neC #assCordText3ield79passCord9::1 add7neC /abel79login)tatus9::1 & public %inal 4oid on)ubmit7: i%7username.eEuals79test9: UU passCord.eEuals79test9:: login)tatus 8 9CongratulationsF91 else login)tatus 8 9Wrong username or passCord F91 & &

-n this .ersion the form itself is used as model obHect for its Compo"ndPropert,Model. This allows children components to ha.e direct access to form fields and use them as bac#ing obHects* without e,plicitly creating a model for themsel.es. >ote Meep in mind that when Compo"ndPropert,Model is inherited* it does not consider the ids of tra.ersed containers for the final property e,pression* but it will always use the id of the .isited child. To understand this potential pitfall* letBs consider the following initialiCation code of a page(
//Create a person named ILohn )mithI #erson person 8 neC #erson79Lohn9, 9)mith9:1 //Create a person named ILill )mithI #erson spouse 8 neC #erson79Lill9, 9)mith9:1 //)et Lill as LohnIs spouse person.set)pouse7spouse:1 set+e%ault;odel7neC Compound#ropert";odel7person::1

Wicket free user guide

6$

> Wicket models and forms

Web;arkupContainer spouse 8 neC Web;arkupContainer79spouse9:1 /abel name1 spouse.add7name 8 neC /abel79name9::1 add7spouse:1

The .alue displayed by label 9name9 will be 9Lohn9 and not the spouseBs name 9Lill9 as you may e,pect. -n this e,ample the label doesnBt own a model* so it must search up its container hierarchy for an inheritable model. 9owe.er* its container ( WebMark"p Container with id BspouseB) doesnBt own a model* hence the reEuest for a model is forwarded to the parent container* which in this case is the page. -n the end the label inherits Compo"ndPropert,Model from page but only its own id is used for the property e,pression. The containers in between are ne.er ta#en into account for the final property e,pression.

4.#

.omponent 5rop5own.hoice

!lass org.apache.wicket.mark"p.html.0orm.:rop:ownChoice is the form component needed to display a list of possible options as a drop-down list where users can select one of the proposed options. This component must be used with <select> tag( 9tml(
<%orm Cicket:id89%orm9> )elect a %ruit: <select Cicket:id89%ruits9></select> <di4><input t"pe89submit9 4alue89submit9/></di4> </%orm>

Ka.a code(
/ist<)tring> %ruits 8 5rra"s.as/ist79apple9, 9straCberr"9, 9Catermelon9:1 %orm.add7neC +rop+oCnChoice<)tring>79%ruits9, neC ;odel7:, %ruits::1

"creenshot of generated page(

-n addition to the component id* in order to build a :rop:ownChoice we need to pro.ide to its constructor two further parameters( a model containing the current selected item. This parameter is not reEuired if we are going to inherit a Comp"ndPropert,Model for this component. a list of options to display which can be supplied as a model or as a regular 5a!a."til.List. -n the e,ample abo.e the possible options are pro.ided as a list of String obHects. loo# at the mar#up generated for them( ow letBs ta#e a

Wicket free user guide

63

> Wicket models and forms

<select name89%ruits9 Cicket:id89%ruits9> <option 4alue899 selected89selected9>Choose 'ne</option> <option 4alue89A9>apple</option> <option 4alue89@9>straCberr"</option> <option 4alue89=9>Catermelon</option> </select>

The first option is a placeholder item corresponding to a n"ll model .alue. By default :rop:ownChoice cannot ha.e a n"ll .alue so users are forced to select a not-null option. -f we want to change this beha.ior we can set the n"ll-alid flag to tr"e .ia the setN"ll-alid method. Please note that the placeholder te,t (F!hose oneG) can be localiCed* as we will see in chapter 14. The other options are identified by the attribute 4alue. By default the .alue of this attribute is the inde, of the single option inside the pro.ided list of choices* while the te,t displayed to the user is obtained by calling toString( on the choice obHect. This default beha.ior wor#s fine as long as our options are simple obHects li#e strings* but when we mo.e to more comple, obHects we may need to implement a more sophisticated algorithm to generate the .alue to use as the option id and the one to display to user. 2ic#et has sol.ed this problem with org.apache.wicket.mark"p.html.0orm.2Choice)ender interface. This interface defines method get:ispla,-al"e(/ ob5ect that is called to generate the .alue to display for the gi.en choice ob5ect* and method get2d-al"e(/ ob5ect4 int inde( that is called to generate the option id. The built-in implementation of this interface is class org.apache.wicket.mark"p.html.Form. Choice)enderer which renders the two .alues using property e,pressions. -n the following code we want to show a list of Person obHects using their full name as .alue to display and using their passport code as option id( Ka.a code(
/ist<#erson> persons1 //$nitialiPe the list o% persons here... Choice*enderer person*enderer 8 neC Choice*enderer79%ullName9, 9passportCode9:1 %orm.add7neC +rop+oCnChoice<)tring>79persons9, neC ;odel<#erson>7:, persons, person*enderer::1

The choice renderer can be assigned to the :rop:ownChoice using one of its constructor that accepts this type of parameter (li#e we did in the e,ample abo.e) or after its creation in.o#ing setChoice)enderer method.

4.( +odel chaining


<odels that implement the interface org.apache.wicket.model.2ChainingModel can be used to build a chain of models. These #inds of models are able to recogniCe whether their model obHect is itself an implementation of 2Model and if so* they will call get+b5ect on the wrapped model and the returned .alue will be the actual model obHect. -n this way we can combine the action of an arbitrary number of models* ma#ing e,actly a chain of models. !haining models allows to combine different data persistence strategies* similarly to what we do with chains of -/@ streams.46 To see model chaining in action we will build a page that implements the :ist/Detail Diew pattern* where we ha.e a drop-down list of Person obHects and a form to display and edit the data of the current
27 http: -ava.sun.com developer technical$rticles Streams ProgI2Streams

Wicket free user guide

65

> Wicket models and forms

selected Person. The e,ample page will loo# li#e this(

2hat we want to do in this e,ample is to chain the model of the :rop:ownChoice (which contains the selected Person) with the model of the Form. -n this way the Form will wor# with the selected Person as bac#ing obHect. The :rop:ownChoice component can be configured to automatically update its model each time we change the selected item on the client side. All we ha.e to do is to o.erride method want+n SelectionChangedNoti0ications to ma#e it return tr"e. -n practice* when this method returns tr"e* :rop:ownChoice will submit its .alue e.ery time Ka.a"cript e.ent onChange occurs* and its model will be conseEuently updated. To le.erage this functionality* :rop:ownChoice doesnBt need to be inside a form. The following is the resulting mar#up of the e,ample page(
... <bod"> /ist o% persons <select Cicket:id89persons9></select> <br/> <br/> <%orm Cicket:id89%orm9> <di4 st"le89displa": table19> <di4 st"le89displa": table-roC19> <di4 st"le89displa": table-cell19>Name: </di4> <di4 st"le89displa": table-cell19> <input t"pe89text9 Cicket:id89name9/> </di4> </di4> <di4 st"le89displa": table-roC19> <di4 st"le89displa": table-cell19>)urname: </di4> <di4 st"le89displa": table-cell19> <input t"pe89text9 Cicket:id89surname9/> </di4> </di4> <di4 st"le89displa": table-roC19> <di4 st"le89displa": table-cell19>5ddress: </di4> <di4 st"le89displa": table-cell19> <input t"pe89text9 Cicket:id89address9/> </di4> </di4> <di4 st"le89displa": table-roC19> <di4 st"le89displa": table-cell19>(mail: </di4> <di4 st"le89displa": table-cell19> <input t"pe89text9 Cicket:id89email9/> </di4> </di4> </di4> <input t"pe89submit9 4alue89)a4e9/> </%orm> </bod">

Wicket free user guide

6A

> Wicket models and forms

...

The initialiCation code for :rop:ownChoice is the following(


;odel<#erson> list;odel 8 neC ;odel<#erson>7:1 Choice*enderer<#erson> person*ender 8 neC Choice*enderer<#erson>79%ullName9:1 persons/ist 8 neC +rop+oCnChoice<#erson>79persons9, list;odel, load#ersons7:, person*ender: !'4erride protected boolean Cant'n)electionChangedNoti%ications7: return true1 & &1

As choice render we ha.e used the basic implementation pro.ided with the org.apache.wicket .mark"p.html.0orm.Choice)enderer class that we ha.e seen in the pre.ious paragraph. loadPersons( is Hust an utility method which generates a list of Person instances. The model for :rop:ownChoice is a simple instance of the Model class. 9ere is the whole code of the page (e,cept for the loadPersons( method)(
public class #erson/ist+etails extends Web#age pri4ate 3orm %orm1 pri4ate +rop+oCnChoice<#erson> persons/ist1 public #erson/ist+etails7: ;odel<#erson> list;odel 8 neC ;odel<#erson>7:1 Choice*enderer<#erson> person*ender 8 neC Choice*enderer<#erson>79%ullName9:1 persons/ist 8 neC +rop+oCnChoice<#erson>79persons9, list;odel, load#ersons7:, person*ender: !'4erride protected boolean Cant'n)electionChangedNoti%ications7: return true1 & &1 add7persons/ist:1 %orm 8 neC 3orm79%orm9, neC Compound#ropert";odel<#erson>7list;odel::1 %orm.add7neC Text3ield79name9::1 %orm.add7neC Text3ield79surname9::1 %orm.add7neC Text3ield79address9::1 %orm.add7neC Text3ield79email9::1 add7%orm:1 & //load#ersons7: //... &

The two models wor# together as a pipeline where the output of method get+b5ect of Model is the

Wicket free user guide

66

> Wicket models and forms

model obHect of Compo"ndPropert,Model. As we ha.e seen* model chaining allows us to combine the actions of two or more models without creating new custom implementations.

4.- 5etacha=le models.


-n chapter A we ha.e seen how 2ic#et uses serialiCation to store page instances. 2hen an obHect is serialiCed* all its referenced obHects are recursi.ely serialiCed. =or a page this means that all its children components* their related models as well as the model obHects inside them will be serialiCed. =or model obHects this could be a serious issue for (at least) two main reasons( 1. The model obHect could be a .ery large instance* hence serialiCation would become .ery e,pensi.e in terms of time and memory. 4. 2e simply may not be able to use a serialiCable obHect as model obHect. -n paragraphs 1.3 and 8.4 we stated that 2ic#et allows us to use a P@K@ as bac#ing obHect* but P@K@s are ordinary obHects with no prespecified interface* annotation or superclass 47* hence they are not reEuired to implement the standard Seriali3able interface. To cope with these problems 2Model e,tends another interface called 2:etachable.

This interface pro.ides a method called detach( which is in.o#ed by 2ic#et at the end of web reEuest processing when data model is no more needed but before serialiCation occurs. @.erriding this method we can clean any reference to data obHect #eeping Hust the information needed to retrie.e it later (for e,ample the id of the table row where our data are stored). -n this way we can a.oid the serialiCation of the obHect wrapped into the model o.ercoming both the problem with nonserialiCable obHects and the one with large data obHects. "ince 2Model inherits from 2:etachable* e.ery model of 2ic#et is FdetachableG* although not all of them implement a detaching policy (li#e the Model class). &sually detaching operations are strictly dependent on the persistence technology adopted for model obHects (li#e a relational db* a o"Q: db* a Eueue* etc...)* so itBs not unusual to write a custom detachable model suited for the persistence technology chosen for a gi.en proHect. To ease this tas# 2ic#et pro.ides abstract model Loadable:etachableModel. This class internally holds a transient reference to a model obHect which is initialiCed the first time get+b5ect( is called to precess a reEuest. The concrete data loading is delegated to abstract method / load( . The reference to a model obHect is automatically set to n"ll at the end of the reEuest by the detach( method . The following class diagram summariCes the methods defined inside Loadable:etachableModel.

28 'ee definition at http%CCen$wikipedia$orgCwikiCPlainD"ldD)avaD"b#ectG.efinition

Wicket free user guide

67

> Wicket models and forms

on:etach and onAttach can be o.erridden in order to obtain further control o.er the detaching procedure. ow as e,ample of a possible use of Loadable:etachableModel* we will build a model designed to wor# with entities managed .ia KPA48. To understand the following code a basic #nowledge of KPA is reEuired e.en if we wonBt go into the detail of this standard. Warning The following model is pro.ided for e,ample purposes only and is not intended to be used in production en.ironment. -mportant aspects such as transaction management are not ta#en into account and you should rewor# the code before considering to use it.

public class Lpa/oadable;odel<T> extends /oadable+etachable;odel<T> pri4ate (ntit";anager3actor" entit";anager3actor"1 pri4ate Class<T> entit"Class1 pri4ate )erialiPable identi%ier1 pri4ate /ist<'b2ect> constructor#arams1 public Lpa/oadable;odel7(ntit";anager3actor" entit";anager3actor", T entit": super7:1 #ersistence0nit0til util 8 entit";anager3actor".get#ersistence0nit0til7:1 this.entit";anager3actor" 8 entit";anager3actor"1 this.entit"Class 8 7Class<T>: entit".getClass7:1 this.identi%ier 8 7)erialiPable: util.get$denti%ier7entit":1 set'b2ect7entit":1 & !'4erride protected T load7: T entit" 8 null1 i%7identi%ier F8 null: (ntit";anager entit";anager 8 entit";anager3actor".create(ntit";anager7:1 entit" 8 entit";anager.%ind7entit"Class, identi%ier:1 & return entit"1 &

29 http: en.wikipedia.org wiki 3ava1Persistence1$PI

Wicket free user guide

68

> Wicket models and forms

!'4erride protected 4oid on+etach7: super.on+etach7:1 T entit" 8 get'b2ect7:1 #ersistence0nit0til persistence0til 8 entit";anager3actor".get#ersistence0nit0til7:1 i%7entit" 88 null: return1 identi%ier 8 7)erialiPable: persistence0til.get$denti%ier7entit":1 & &

The constructor of the model ta#es as input two parameters( an implementation of the KPA interface 5a!a(.persistence.'ntit,ManagerFactor, to manage KPA entities and the entity that must be handled by this model. -nside its constructor the model sa.es the class of the entity and its id (which could be n"ll if the entity has not been persisted yet). These two informations are reEuired to retrie.e the entity at a later time and are used by the load method. on:etach is responsible for updating the entity id before detachment occurs. The id can change the first time an entity is persisted (KPA generates a new id and assigns it to the entity). Please note that this model is not responsible for sa.ing any changes occurred to the entity obHect before it is detached. -f we donBt want to loose these changes we must e,plicitly persist the entity before the detaching phase occurs. Warning "ince the model of this e,ample holds a reference to the 'ntit,Manager Factor,* the implementation in use must be serialiCable.

4.' 0sing more than one model in a component


"ometimes our custom components may need to use more than a single model to wor# properly. -n such a case we must manually detach the additional models used by our components. -n order to do this we can o.erwrite the ComponentBs on:etach method that is called at the end of the current reEuest. The following is the generic code of a component that uses two models(
/** * * %oo;odel is used as main model Chile bee;odel must be manuall" detached * */ public class ComponetTCo;odels extends Component pri4ate $;odel<.ee> bee;odel1 public ComponetTCo;odels7)tring id, $;odel<3oo> %oo;odel, $;odel<.ee> bee;odel: super7id, %oo;odel:1 this.bee;odel 8 bee;odel1 & !'4erride public 4oid on+etach7:

Wicket free user guide

7%

> Wicket models and forms

i%7bee;odel F8 null: bee;odel.detach7:1 super.on+etach7:1 & &

2hen we o.erwrite on:etach we must call the super class implementation of this method* usually as last line in our custom implementation.

4.2 0se models%


:i#e many people new to 2ic#et* you may need a little time to fully understand the power and the ad.antages of using models. Ta#ing your first steps with 2ic#et you may be tempted to pass row obHects to your components instead of using models(
/** * * N'T T' +': passing roC ob2ects to components instead o% using modelsF * */ public class CustomComponent extends Component pri4ate 3oo.ean %oo.ean1 public CustomComponent7)tring id, 3oo.ean %oo.ean: super7id:1 this.%oo.ean 8 %oo.ean1 & //...some other ugl" code ::... &

ThatBs a bad practice and you must a.oid it. &sing models we do not only decouple our components from the data source* but we can also relay on them (if they are dynamic) to wor# with the most up-todate .ersion of our model obHect. -f we decide to bypass models we lose all these ad.antages and we force model obHects to be serialiCed.

4.4 8ummar
<odels are at the core of 2ic#et and they are the basic ingredient needed to taste the real power of the framewor#. -n this chapter we ha.e seen how to use models to bring data to our components without littering their code with technical details about their persistence strategy. 2e ha.e also introduced 2ic#et forms as complementary topic. 2ith forms and models we are able to bring our applications to life allowing them to interact with users. But what we ha.e seen in this chapter about 2ic#et forms is Hust the tip of the iceberg. ThatBs why the ne,t chapter is entirely dedicated to them.

Wicket free user guide

71

1E Wicket forms in detail

1/ Wicket forms in detail


-n the pre.ious chapter we ha.e only scratched the surface of 2ic#et forms. The Form component was not only designed to collect user input but also to e,tend the semantic of the classic 9T<: forms with new features. @ne of such features is the ability to wor# with nested forms (they will be discussed in paragraph 1%.5). -n this chapter we will continue to e,plore 2ic#et forms learning how to master them and how to build effecti.e and user-proof forms for our web applications.

1/.1 5efault form processing


-n paragraph 8.$ we ha.e seen a .ery basic usage of the Form component and we didnBt pay much attention to what happens behind the scenes of form submission. -n 2ic#et when we submit a form we trigger the following steps on ser.er side( 1. Horm validation: user input is chec#ed to see if it satisfies the .alidation rules set on the form. -f .alidation fails* step number 4 is s#ipped and the form should display a feedbac# message to e,plain to user what went wrong. During this step input .alues (which are simple strings sent with a web reEuest) are con.erted into Ka.a obHects. -n the ne,t paragraphs we will e,plore the infrastructures pro.ided by 2ic#et for the three subtas#s in.ol.ed with form .alidation* which are( conversion of user input into ob-ects * validation of user input* and visuali<ation of feedback messages. 4. 0pdating of models: if .alidation succeeds* the form updates the model of its children components with the con.erted .alues obtained in the pre.ious step. $. !nvoking call=ack methods on)u*mit+, or on-rror+,: if we didnBt ha.e any .alidation error* method onS"bmit( is called* otherwise on'rror( will be called. The default implementation of both these methods is left empty and we can o.erride them to perform custom actions. >ote Please note that the model of form components is updated only if no .alidation error occurred (i.e. step two is performed only if .alidation succeeds). 2ithout going into too much detail* we can say that the first two steps of form processing correspond to the in.ocation of one or more FormBs internal methods (which are declared protected and 0inal). "ome e,amples of these methods are !alidate( * which is in.o#ed during .alidation step* and "pdateFormComponentModels( * which is used at the step that updates the form field models. The whole form processing is started in.o#ing public method process(2FormS"bmitter (:ater in paragraph 1%.3 we will introduce interface 2FormS"bmitter).

1/.2 Horm validation and feed=ack messages


A basic e,ample of a .alidation rule is to ma#e a field reEuired. -n paragraph 8.$.4 we ha.e already seen how this can be done calling set)e6"ired(tr"e on a field. 9owe.er* to set a .alidation rule on a FormComponent we must add the corresponding validator to it. A validator is an implementation of the org.apache.wicket.!alidation.2-alidator interface and the FormComponent has a .ersion of method add which ta#es as input a reference of this interface.
Wicket free user guide

74

1E Wicket forms in detail

=or e,ample if we want to use a te,t field to insert an email address* we could use the built-in .alidator 'mailAddress-alidator to ensure that the inserted input will respect the email format local@ partAdomainBC(
Text3ield email 8 neC Text3ield79email9:1 email.add7neC (mail5ddressOalidator7::1

2ic#et comes with a set of built-in .alidators that should suit most of our needs. 2e will see them in paragraph 1%.4.$.

1/.2.1

Heed=ack messages and locali6ation

2ic#et generates a feedbac# message for each field that doesnBt satisfy one of its .alidation rules. =or e,ample the message generated when a reEuired field is left empty is the following
3ield I<label>I is reEuired.

is the .alue of the label model set on a FormComponent with method setLabel(2Model 7String8 model . -f such model is not pro.ided* component id will be used as the default .alue. The entire infrastructure of feedbac# messages is built on top of the Ka.a internationaliCation (-17 ) support and it uses resource bundles=> to store messages.
<label>

>ote The topics of internationaliCation will be co.ered in chapter 14. =or now we will gi.e Hust few notions needed to understand the e,amples from this chapter. By default resource bundles are stored into properties files but we can easily configure other sources as described later in paragraph 14.3.5. Default feedbac# messages (li#e the one abo.e for reEuired fields) are stored in the file $pplication. properties placed inside 2ic#et the org.apache.wicket pac#age. @pening this file we can find the #ey and the localiCed .alue of the message(
*eEuired83ield IW label&I is reEuired.

2e can note the #ey (*eEuired in our case) and the label parameter written in the e0pression language=+ (W label&). "crolling down this file we can also find the message used by the 'mail Address-alidator(
(mail5ddressOalidator8The 4alue o% IW label&I is not a 4alid email address.

By default FormComponent pro.ides $ parameters for feedbac# message( .alidation)* label and name (this later is the id of the component). Warning

input

(the .alue that failed

+emember that component model is updated with the user input only if .alidation succeeds; As a conseEuence* we canBt retrie.e the wrong .alue
30 http: en.wikipedia.org wiki #mail1address 31 http: docs.oracle.com -avase tutorial i>?n resbundle inde0.html 32 http: en.wikipedia.org wiki #0pression1%anguage

Wicket free user guide

7$

1E Wicket forms in detail

inserted for a field from its model. -nstead* we should use get-al"e( method of FormComponent class. (This method will be introduced in the e,ample used in paragraph 1%.4.5)

1/.2.2

5isplaing feed=ack messages and filtering them

To display feedbac# messages we must use component org.apache.wicket.mark"p.html. panel.FeedbackPanel. This component automatically reads all the feedbac# messages generated during form .alidation and displays them with an unordered list(
<ul class89%eedback#anel9> <li class89%eedback#anel(**'*9> <span class89%eedback#anel(**'*9>3ield I0sernameI is reEuired.</span> </li> </ul>

!"" classes Xfeedbac#PanelX and Xfeedbac#PanelI++@+X can be used in order to customiCe the style of the message list$$(

llustration 1E$1% Hxample of styling of feedback messages list The component can be freely placed inside the page and we can set the ma,imum amount of displayed messages with the setMa(Messages( method. Irror messages can be filtered using three built-in filters( .omponentHeed=ack+essageHilter: shows only messages coming from a specific component. .ontainerHeed=ack+essageHilter: shows only messages coming from a specific container or from any of its children components. Drror,evelHeed=ack+essageHilter: shows only messages with a le.el of se.erity eEuals or greater than a gi.en lower bound. !lass FeedbackMessage defines a set of static constants to e,press different le.els of se.erity( DIB&0* I++@+* 2A+ - 0* - =@* "&!!I""* etc.... :e.els of se.erity for feedbac# messages are discussed in paragraph 1%.4.A. These filters are intended to be used when there are more than one feedbac# panel (or more than one form) in the same page. 2e can pass a filter to a feedbac# panel .ia its constructor or using the setFilter method. !ustom filters can be created implementing the 2FeedbackMessageFilter interface. An e,ample of custom filter is illustrated on page 78.

1/.2.3

;uilt?in validators

2ic#et already pro.ides a number of built-in .alidators ready to be used. The following table is a short reference where .alidators are listed along with a brief description of what they do. The default feedbac# message used by each of them is reported as well(

33 The style of llustration 1E$1 was created by 3anko 3ovanovic$ 'ee http: css.d<one.com news css*message*bo0es*different*me

Wicket free user guide

73

1E Wicket forms in detail

>ame
ImailAddressDalidator &rlDalidator

5escription

+essage

!hec#s if input respects the format The 4alue o% IW label&I is not a 4alid email address. local@partAdomain !hec#s if input is a .alid &+:. 2e can The 4alue o% IW label&I is not a specify in the constructor which 4alid 0*/. protocols are allowed (http://* https://* and ftp://). Dalidator class that can be e,tended or used as a factory class to get date .alidators to chec# if a date is bigger than a lower bound (method minim"m(:ate min))* smaller than a upper bound (method ma(im"m(:ate ma( ) or inside a range (method range(:ate min4 :ate ma( ).
Hor minimum validator: The 4alue o% IW label&I is less than the minimum o% W minimum&.

DateDalidator

Hor maximum validator: The 4alue o% the IW label&I maximum o% is W larger than maximum&.

Hor range validator: The 4alue o% IW label&I is not betCeen W minimum& maximum&. and W

+angeDalidator

Dalidator class that can be e,tended or used as a factory class to get .alidators to chec# if a .alue is bigger than a gi.en lower bound (method minim"m(/ min))* smaller than a upper bound (method ma(im"m(/ ma( ) or inside a range (method range(/ min4/ ma( ).

Hor minimum validator: The 4alue o% IW label&I must be at least W minimum&.

Hor maximum validator: The 4alue o% IW label&I must be at most W maximum&.

The type of the .alue is a generic Hor range validator: subtype of 5a!a.lang.Comparable The 4alue o% IW label&I must be and must implement Seriali3able betCeen W minimum& and W interface. maximum&. "tringDalidator Dalidator class that can be e,tended or used as a factory class to get .alidators to chec# if the length of a string .alue is bigger then a gi.en lower bound (method minim"mLength (int min )* smaller then a gi.en upper bound (method ma(im"mLength (int ma( ) or within a gi.en range (method length1etween(int min4 int ma( ).
Hor minimum validator: The 4alue o% IW label&I is shorter than the minimum o% W minimum& characters.

Hor maximum validator: The 4alue o% IW label&I is longer than the maximum o% W maximum& characters.

To accept only string .alues consisting Hor range validator: of e,actly n characters* we must use The 4alue o% IW label&I is not method e(actLength(int length . betCeen W minimum& and W
maximum& characters long.

Wicket free user guide

75

1E Wicket forms in detail

Hor exact validator: The 4alue o% IW label&I is not exactl" W exact& characters long.

!redit!ardDalidator

!hec#s if input is a .alid credit card The credit number. This .alidator supports some of in4alid. the most popular credit cards (li#e FAmerican I,pressX* X<aster!ardX* FDisaG or FDiners !lubG).

card

number

is

IEualPassword-nputDalidator This .alidator chec#s if two password W labelA& and W label@& must be eEual. fields ha.e the same .alue.

1/.2.#

Cverriding standard feed=ack messages with custom =undles

-f we donBt li#e the default .alidation feedbac# messages* we can o.erride them pro.iding custom properties files. -n these files we can write our custom messages using the same #eys of the messages we want to o.erride. =or e,ample if we wanted to o.erride the default message for in.alid email addresses* our properties file would contain a line li#e this(
(mail5ddressOalidator8;an, "our email address is not goodF

As we will see in the ne,t chapter* 2ic#et searches for custom properties files in .arious positions inside the applicationBs class path* but for now we will consider Hust the properties file placed ne,t to our application class. The name of this file must be eEual to the name of our application class(

The e,ample proHect 2verride4ail4essage o.errides email .alidatorBs message with a new one which also reports the .alue that failed .alidation(
(mail5ddressOalidator8The 4alue IW input&I inserted %or %ield IW label&I is not a 4alid email address.

1/.2.(

.reating custom validators

-f our web application reEuires a comple, .alidation logic and built-in .alidators are not enough* we can implement our own custom .alidators. =or e,ample (proHect :sername(ustom6alidator) suppose we are wor#ing on the registration page of our site where users can create their profile choosing their username. @ur registration form should .alidate the new username chec#ing if it was already chosen by

Wicket free user guide

7A

1E Wicket forms in detail

another user. -n a situation li#e this we may need to implement a custom .alidator that Eueries a specific data source to chec# if a username is already in use. =or the sa#e of simplicity* the .alidator of our e,ample will chec# the gi.en username against a fi,ed list of three e,isting usernames. A custom .alidator must simply implement interface 2-alidator(
public class 0sernameOalidator implements $Oalidator<)tring> /ist<)tring> existing0sernames 8 5rra"s.as/ist79bigLack9, 9anon"mous9, 9mr)mith9:1 public 4oid 4alidate7$Oalidatable<)tring> 4alidatable: )tring chosen0serName 8 4alidatable.getOalue7:1 i%7existing0sernames.contains7chosen0serName:: Oalidation(rror error 8 neC Oalidation(rror7this:1 *andom random 8 neC *andom7:1 error.setOariable79suggested0serName9, 4alidatable.getOalue7: > random.next$nt7::1 4alidatable.error7error:1 & & &

The only method defined inside 2-alidator is !alidate(2-alidatable7/8 !alidatable and is in.o#ed during .alidationBs step. -nterface 2-alidatable represents the component being .alidated and it can be used to retrie.e the component model ( getModel( ) or the .alue to .alidate (get-al"e( ). The custom .alidation logic is all inside 2-alidatorBs method !alidate. 2hen .alidation fails a .alidator must use 2-alidatableBs method error(2-alidation'rror error to generate the appropriate feedbac# message. -n the code abo.e we used the -alidation'rror class as con.enience implementation of the 2-alidation'rror interface which represents the .alidation error that must be displayed to the user. This class pro.ides a constructor that uses the class name of the .alidator in input as #ey for the resource to use as feedbac# message (i.e. B 0sernameOalidatorB in the e,ample). -f we want to specify more then one #ey to use to locate the error message* we can use method add;e,(String ke, of -alidation'rror class. -n our e,ample when .alidation fails* we suggest a possible username concatenating the gi.en input with a pseudo-random integer. This .alue is passed to the feedbac# message with a .ariable named s"ggested9serName. The message is inside applicationBs properties file(
0sernameOalidator8The username IW input&I is alread" in use. Tr" Cith IW suggested0serName&I

To pro.ide further .ariables to our feedbac# message we can use method set-ariable(String name4 +b5ect !al"e of class -alidation'rror as we did in our e,ample. The code of the home page of the proHect will be e,amined in the ne,t paragraph after we ha.e introduced the topic of flash messages. 1/.2.0sing flash messages

"o far we ha.e considered Hust the error messages generated during .alidation step. 9owe.er 2ic#etBs Component class pro.ides a set of methods to e,plicitly generate feedbac# messages called flash messages. These methods are(

Wicket free user guide

76

1E Wicket forms in detail

deb"g(Seriali3able message in0o(Seriali3able message s"ccess(Seriali3able message warn(Seriali3able message error(Seriali3able message 0atal(Seriali3able message

Iach of these methods corresponds to a level of severity for the message. The list abo.e is sorted by increasing le.el of se.erity. -n the e,ample seen in the pre.ious paragraph we ha.e a form which uses s"ccess method to notify user when the inserted username is .alid. -nside this form there are two FeedbackPanel components( one to display the error message produced by custom .alidator and the other one to display the success message. The code of the e,ample page is the following( 9tml(
<bod"> <%orm Cicket:id89%orm9> 0sername: <input t"pe89text9 Cicket:id89username9/> <br/> <input t"pe89submit9/> </%orm> <di4 st"le89color:green9 Cicket:id89succes;essage9> </di4> <di4 st"le89color:red9 Cicket:id89%eedback;essage9> </di4> </bod">

Ka.a code(
public class Dome#age extends Web#age public Dome#age7%inal #age#arameters parameters: 3orm %orm 8 neC 3orm79%orm9: !'4erride protected 4oid on)ubmit7: super.on)ubmit7:1 success790sername is goodF9:1 & &1 Text3ield mail1 %orm.add7mail 8 neC Text3ield79username9, ;odel.o%799:::1 mail.add7neC 0sernameOalidator7::1 add7neC 3eedback#anel79%eedback;essage9, neC (xact(rror/e4el3ilter73eedback;essage.(**'*:::1 add7neC 3eedback#anel79succes;essage9, neC (xact(rror/e4el3ilter73eedback;essage.)0CC()):::1 add7%orm:1 & class (xact(rror/e4el3ilter implements $3eedback;essage3ilter

Wicket free user guide

77

1E Wicket forms in detail

pri4ate int error/e4el1 public (xact(rror/e4el3ilter7int error/e4el: this.error/e4el 8 error/e4el1 & public boolean accept73eedback;essage message: return message.get/e4el7: 88 error/e4el1 & & //0sernameOalidator de%inition //... &

The two feedbac# panels must be filtered in order to display Hust the messages with a gi.en le.el of se.erity (I++@+ for .alidator message and "&!!I"" for formBs flash message). &nfortunately the built-in message filter 'rrorLe!elFeedbackMessageFilter is not suitable for this tas# because its filter condition does not chec# for an e,act error le.el (the gi.en le.el is used as lower bound .alue). As a conseEuence* we had to build a custom filter (inner class '(act'rrorLe!elFilter) to accept only the desired se.erity le.el (see method accept of interface 2FeedbackMessageFilter).

1/.3 !nput value conversion


2or#ing with 2ic#et we will rarely need to worry about con.ersion between input .alues (which are strings because the underlying 9TTP protocol) and Ka.a types because in most cases the default con.ersion mechanism will be smart enough to infer the type of the model obHect and perform the proper con.ersion. 9owe.er* sometimes we may need to wor# under the hood of this mechanism to ma#e it properly wor# or to perform custom con.ersions. ThatBs why this paragraph will illustrate how to control input .alue con.ersion. The component that is responsible for con.erting input is the FormComponent itself with its con!ert2np"t( method. -n order to con.ert its input a FormComponent must #now the type of its model obHect. This parameter can be e,plicitly set with method set/,pe(Class7D8 t,pe (
//this %ield must recei4e an integer 4alue Text3ield integer3ield 8 neC Text3ield79number9, neC ;odel7::.setT"pe7$nteger.class::1

-f no type has been pro.ided* FormComponent will try to as# its model for this information. The Propert,Model and Compo"ndPropert,Model models can use reflection to get the type of obHect model. By default* if FormComponent can not obtain the type of its model obHect in any way* it will consider it as a simple String. @nce FormComponent has determined the type of model obHect* it can loo# up for a converter* which is the entity in charge of con.erting input to Ka.a obHect and .ice .ersa. !on.erters are instances of org.apache.wicket."til.con!ert.2Con!erter interface and are registered by our application class on start up. To get a con.erter for a specific type we must call method getCon!erter(Class7C8 t,pe on the interface 2Con!erterLocator returned by ApplicationBs method getCon!erterLocator( (
//retrie4e con4erter %or .oolean t"pe 5pplication.get7:.getCon4erter/ocator7:.getCon4erter7.oolean.class:1

Wicket free user guide

78

1E Wicket forms in detail

>ote !omponents which are subclasses of AbstractSingleSelectChoice donBt follow the schema illustrated abo.e to con.ert user input. These #inds of components (li#e :rop:ownChoice and )adioChoiceBE) use their choice render and their collection of possible choices to perform input con.ersion.

1/.3.1

.reating custom application?scoped converters

The default con.erter locator used by 2ic#et is org.apache.wicket.Con!erterLocator. This class pro.ides con.erters for the most common Ka.a types. 9ere we can see the con.erters registered inside its constructor(
public Con4erter/ocator7: set7.oolean.TG#(, .ooleanCon4erter.$N)T5NC(:1 set7.oolean.class, .ooleanCon4erter.$N)T5NC(:1 set7."te.TG#(, ."teCon4erter.$N)T5NC(:1 set7."te.class, ."teCon4erter.$N)T5NC(:1 set7Character.TG#(, CharacterCon4erter.$N)T5NC(:1 set7Character.class, CharacterCon4erter.$N)T5NC(:1 set7+ouble.TG#(, +oubleCon4erter.$N)T5NC(:1 set7+ouble.class, +oubleCon4erter.$N)T5NC(:1 set73loat.TG#(, 3loatCon4erter.$N)T5NC(:1 set73loat.class, 3loatCon4erter.$N)T5NC(:1 set7$nteger.TG#(, $ntegerCon4erter.$N)T5NC(:1 set7$nteger.class, $ntegerCon4erter.$N)T5NC(:1 set7/ong.TG#(, /ongCon4erter.$N)T5NC(:1 set7/ong.class, /ongCon4erter.$N)T5NC(:1 set7)hort.TG#(, )hortCon4erter.$N)T5NC(:1 set7)hort.class, )hortCon4erter.$N)T5NC(:1 set7+ate.class, neC +ateCon4erter7::1 set7Calendar.class, neC CalendarCon4erter7::1 set72a4a.sEl.+ate.class, neC )El+ateCon4erter7::1 set72a4a.sEl.Time.class, neC )ElTimeCon4erter7::1 set72a4a.sEl.Timestamp.class, neC )ElTimestampCon4erter7::1 set7.ig+ecimal.class, neC .ig+ecimalCon4erter7::1 &

-f we want to add more con.erters to our application* we can o.erride ApplicationBs method newCon!erterLocator which is used by application class to build its con.erter locator. To illustrate how to implement custom con.erters and use them in our application* we will build a form with two te,t field( one to input a regular e,pression pattern and another one to input a string .alue that will be split with the gi.en pattern. The first te,t field will ha.e an instance of class 5a!a."til.rege(.Pattern as model obHect. The final page will loo# li#e this (the code of this e,ample is from the (ustom(onverter proHect)(

34 AadioChoice is introduced in paragraph 1E$1E$1

Wicket free user guide

8%

1E Wicket forms in detail

llustration 1E$*% 7 form with a Text(ield using a #ava$util$regex$Pattern as model ob#ect The con.ersion between Pattern and String is Euite straightforward. The code of our custom con.erter is the following(
public class *eg(xp#atternCon4erter implements $Con4erter<#attern> !'4erride public #attern con4ertTo'b2ect7)tring 4alue, /ocale locale: return #attern.compile74alue:1 & !'4erride public )tring con4ertTo)tring7#attern 4alue, /ocale locale: return 4alue.to)tring7:1 & &

<ethods declared by interface 2Con!erter ta#e as input a Locale parameter in order to deal with locale-sensiti.e data and con.ersions. 2e will learn more about locales and internationaliCation in chapter 14. @nce we ha.e implemented our custom con.erter* we must o.erride method newCon!erterLocator( inside our application class and tell it to add our new con.erter to the default set(
!'4erride protected $Con4erter/ocator neCCon4erter/ocator7: Con4erter/ocator de%ault/ocator 8 neC Con4erter/ocator7:1 de%ault/ocator.set7#attern.class, neC *eg(xp#atternCon4erter7::1 return de%ault/ocator1 &

=inally* in the home page of the proHect we build the form which displays (with a flash message) the to#ens obtained splitting the string with the gi.en pattern(
public class Dome#age extends Web#age pri4ate #attern reg(xp#atter1 pri4ate )tring stringTo)plit1

Wicket free user guide

81

1E Wicket forms in detail

public Dome#age7%inal #age#arameters parameters: Text3ield mail1 Text3ield stringTo)plitTxt1 3orm %orm 8 neC 3orm79%orm9: !'4erride protected 4oid on)ubmit7: super.on)ubmit7:1 )tring message*esult 8 9Tokens %or the gi4en string and pattern:<br/>91 )tringHJ tokens 8 reg(xp#atter.split7stringTo)plit:1 %or 7)tring token : tokens: message*esult >8 9- 9 > token > 9<br/>91 & success7message*esult:1 & &1 %orm.set+e%ault;odel7neC Compound#ropert";odel7this::1 %orm.add7mail 8 neC Text3ield79reg(xp#atter9::1 %orm.add7stringTo)plitTxt 8 neC Text3ield79stringTo)plit9::1 add7neC 3eedback#anel79%eedback;essage9:.set(scape;odel)trings7%alse::1 add7%orm:1 & &

>ote -f the user input can not be con.erted to the target type* FormComponent will generate the default error message F The 4alue o% IW label&I is not a 4alid W t"pe&.G. The bundle #ey for this message is $Con4erter.

1/.# 8u=mit form with an !Horm8u=mitting.omponent


Besides submitting forms with a standard 9T<: submit button* 2ic#et allows us to use special components which implement interface 2FormS"bmittingComponent. This entity is a subinterface of 2FormS"bmitterF

At the beginning of this chapter we ha.e seen that form processing is started by process method

Wicket free user guide

84

1E Wicket forms in detail

which ta#es as input an instance of 2FormS"bmitter. This parameter corresponds to the 2FormS"bmittingComponent clic#ed by a user to submit the form and it is n"ll if we ha.e used a standard 9T<: submit button (li#e we ha.e done so far). A submitting component is added to a form Hust li#e any other child component using method add(Component... . A form can ha.e any number of submitting components and we can specify which one among them is the default one by calling the FormBs method set:e0a"lt1"tton(2FormS"bmittingComponent component . The default submitter is the one that will be used when user presses BInterB #ey in a field of the form. -n order to ma#e the default button wor#* 2ic#et will add to our form a hidden <di4> tag containing a te,t field and a submit button with some Ka.a"cript code to trigger it(
<di4 st"le89Cidth:Apx1height:Apx1position:absolute1le%t:-@AApx1top:-@AApx1

o4er%loC:hidden9>
<input t"pe89text9 autocomplete89o%%9/> <input t"pe89submit9 name89submit=9 onclick89 4ar b8document....9/> </di4>

Kust li#e 2ic#et forms* interface 2FormS"bmitter defines methods onS"bmit and on'rror. These two methods ha.e the priority o.er the namesa#e methods of the form* meaning that when a form is submitted with an 2FormS"bmitter* the onS"bmit of the submitter is called before the one of the form. "imilarly* if .alidation errors occurs during the first step of form processing* submitterBs method on'rror is called before the formBs one. >ote "tarting with 2ic#et .ersion A.% interface 2FormS"bmitter defines a further callbac# method called onA0terS"bmit( . This method is called after formBs method onS"bmit( has been e,ecuted.

1/.#.1

.omponents ;utton and 8u=mit,ink

!omponent org.apache.wicket.mark"p.html.0orm.1"tton is a basic implementation of a form submitter. -t can be used with either the <input> or <button> tags. The string model recei.ed as input by its constructor is used as button label and it will be the .alue of the mar#up attribute 4alue. -n the following snippet we ha.e a form with two submit buttons bound to an <input> tag. @ne of them is set as default button and both ha.e a string model for the label( 9tml(
<bod"> <%orm Cicket:id89%orm9> 0sername: <input t"pe89text9 Cicket:id89username9/> <br/> <input t"pe89submit9 Cicket:id89submit@9/> <input t"pe89submit9 Cicket:id89submit=9/> </%orm> </bod">

Ka.a code(
public class Dome#age extends Web#age public Dome#age7%inal #age#arameters parameters: 3orm %orm 8 neC 3orm79%orm9:1

Wicket free user guide

8$

1E Wicket forms in detail

%orm.add7neC Text3ield79username9, ;odel.o%799:::1 %orm.add7neC .utton79submit@9, ;odel.o%793irst submitter9:::1 .utton second)ubmitter1 %orm.add7second)ubmitter 8 neC .utton79submit=9, ;odel.o%79)econd submitter9:::1 %orm.set+e%ault.utton7second)ubmitter:1 add7%orm:1 & &

0enerated mar#up(
<%orm Cicket:id89%orm9 id89%orm@9 method89post9 action89?A-@.$3orm)ubmit/istener-%orm9> <di4> ... <F-- Code generated b" Wicket to handle the de%ault button --> ... </di4> 0sername: <input t"pe89text9 Cicket:id89username9 4alue899 name89username9/> <br/> <input t"pe89submit9 Cicket:id89submit@9 name89submit@9 id89submit@R9 4alue893irst submitter9/> <input t"pe89submit9 Cicket:id89submit=9 name89submit=9 id89submit==9 4alue89)econd submitter9/> </%orm>

Another component that can be used to submit a form is org.apache.wicket.mark"p. html.0orm.S"bmitLink. This component uses Ka.a"cript to submit the form. :i#e the name suggests* the component can be used with the <a> tag but it can be also bound to any other tag that supports the e.ent handler onclick. 2hen used with the <a> tag* the Ka.a"cript code needed to submit the form will be placed inside hre% attribute while with other tags the script will go inside the e.ent handler onclick. A notable difference between this component and 1"tton is that S"bmitLink can be placed outside the form it must submit. -n this case we must specify the form to submit in its constructor( 9tml(
<html xmlns:Cicket89http://Cicket.apache.org9> <head> </head> <bod"> <%orm Cicket:id89%orm9> #assCord: <input t"pe89passCord9 Cicket:id89passCord9/> <br/> </%orm> <button Cicket:id89external)ubmitter9> )ubmit </button> </bod"> </html>

Ka.a code(

Wicket free user guide

83

1E Wicket forms in detail

public class Dome#age extends Web#age public Dome#age7%inal #age#arameters parameters: 3orm %orm 8 neC 3orm79%orm9:1 %orm.add7neC #assCordText3ield79passCord9, ;odel.o%799:::1 //speci%" the %orm to submit add7neC )ubmit/ink79external)ubmitter9, %orm::1 add7%orm:1 & &

1/.#.2

5isa=ling default form processing

2ith an 2FormS"bmittingComponent we can choose to s#ip the default form submission process by setting the appropriate flag to false with the set:e0a"ltFormProcessing method. 2hen the default form processing is disabled only the submitterBs onS"bmit is called while formBs .alidation and models updating are s#ipped. This can be useful if we want to implement a F!ancelG button on our form which redirects user to another page without .alidating his/her input. 2hen we set this flag to false we can decide to manually in.o#e the form processing by calling the process(2FormS"bmittingComponent method.

1/.( >ested forms


As you might already #nown* 9T:< doesnBt allow to ha.e nested forms $5. 9owe.er with 2ic#et we can o.ercome this limitation by adding one or more form components to a parent form. This can be useful if we want to split a big form into smaller ones in order to reuse them and to better distribute responsibilities among different components. =orms can be nested to an arbitrary le.el(
<%orm Cicket:id89outer3orm9> ... <%orm Cicket:id89inner3orm9> ... <%orm Cicket:id894er"$nner3orm9> ... </%orm> </%orm> </%orm>

2hen a form is submitted also its nested forms are submitted and they participate in the .alidation step. This means that if a nested form contains in.alid input .alues* the outer form wonBt be submitted. @n the contrary* nested forms can be singularly submitted without depending on the status of their outer form. To submit a parent form when one of its children forms is submitted* we must o.erride its method wantS"bmit+nNestedFormS"bmit and ma#e it return tr"e.

1/.- +ulti?line text input


9T<: pro.ides a multi-line te,t input control with
<textarea>

tag. The 2ic#et counterpart for this #ind

35 'ee http: www.w=.org 4ark:p html= forms.html where it is stated% :There can be several forms in a single document6 but the ("A/ element can:t be nested$:

Wicket free user guide

85

1E Wicket forms in detail

of control is org.apache.wicket.mark"p.html.0orm./e(tArea component( <ar#up code(


<textarea Cicket:id89description9 roCs89T9 cols89<A9></textarea>

Ka.a code(
%orm.add7neC Text5rea79description9, ;odel.o%799:::1

!omponent /e(tArea is used Hust li#e any other single-line te,t field. To specify the siCe of the te,t area we can write attributes roCs and cols directly in the mar#up file or we can create new attribute modifiers and add them to our /e(tArea component.

1/.' Hile upload


2ic#et supports file uploading with the File9ploadField component which must be used with the tag whose t"pe attribute must be set to 9%ile9. -n order to send a file on form submission we must enable multipart mode calling M"ltiPart(tr"e on our form. -n the ne,t e,ample (proHect :ploadSingle;ile) we will see a form which allows users to upload a file into the temporary directory of the ser.er (path <tmp on &ni,/:inu, systems)(
<input>

9tml(
<html> <head> </head> <bod"> <h@>0pload "our %ile hereF</h@> <%orm Cicket:id89%orm9> <input t"pe89%ile9 Cicket:id89%ile0pload3ield9/> <input t"pe89submit9 4alue890pload9/> </%orm> <di4 Cicket:id89%eedback#anel9> </di4> </bod"> </html>

Ka.a code(
public class Dome#age extends Web#age pri4ate 3ile0pload3ield %ile0pload3ield1 public Dome#age7%inal #age#arameters parameters: %ile0pload3ield 8 neC 3ile0pload3ield79%ile0pload3ield9:1 3orm %orm 8 neC 3orm79%orm9: !'4erride protected 4oid on)ubmit7: super.on)ubmit7:1 3ile0pload %ile0pload 8 %ile0pload3ield.get3ile0pload7:1

Wicket free user guide

8A

1E Wicket forms in detail

tr" 3ile %ile 8 neC 3ile7)"stem.get#ropert"792a4a.io.tmpdir9: > 9/9 > %ile0pload.getClient3ileName7::1 %ile0pload.CriteTo7%ile:1 & catch 7$'(xception e: e.print)tackTrace7:1 & & &1 %orm.set;ulti#art7true:1 //set a limit %or uploaded %ileIs siPe %orm.set;ax)iPe7."tes.kilob"tes7@AA::1 %orm.add7%ile0pload3ield:1 add7neC 3eedback#anel79%eedback#anel9::1 add7%orm:1 & &

The code that copies the uploaded file to the temporary directory is inside the onS"bmit method of the Form class. The uploaded file is handled with an instance of class File9pload returned by the getFile9pload( method of the File9ploadField class. This class pro.ides a set of methods to perform some common tas#s li#e getting the name of the uploaded file ( getClientFileName( )* coping the file into a directory ( write/o(destinationFile )* calculating file digest (get:igest (digestAlgorithm ) and so on. Form component can limit the siCe for uploaded files using its setMa(Si3e(si3e method. -n the e,ample we ha.e set this limit to 1%% #b to pre.ent users from uploading files bigger than this siCe. >ote The ma,imum siCe for uploaded files can also be set at applicationBs le.el using the set:e0a"ltMa(im"m9ploadSi3e(1,tes ma(Si3e method of the 2ApplicationSettings interface(
!'4erride public 4oid init7: get5pplication)ettings7:.set+e%ault;aximum0pload)iPe7."tes.

kilob"tes7@AA::1
&

1/.'.1

0pload multiple files

-f we need to upload multiple files at once* we can use the M"ltiFile9ploadField component which allows the user to select an arbitrary number of files to send on form submission. An e,ample showing how to use this component can be found in 2ic#et module wicket@e(amples in file M"lti9ploadPage.5a!a. The li.e e,ample is hosted at http(//www.wic#et-library.com/wic#ete,amples-A.%.,/upload/multi.

1/.2 .reating complex form components with Horm.omponentPanel


-n chapter $.4.4 we ha.e seen how to use class Panel to create custom components with their own

Wicket free user guide

86

1E Wicket forms in detail

mar#up and with an arbitrary number of children components. 2hile itBs perfectly legal to use Panel also to group form components* the resulting component wonBt be itself a form component and it wonBt participate in the formBs submission wor#flow. This could be a strong limitation if the custom component needs to coordinate its children during subtas#s li#e input con.ersion or model updating. ThatBs why in 2ic#et we ha.e the org.apache. wicket.mark"p.html.0orm.FormComponentPanel component which combines the features of a Panel (it has its own mar#up file) and a FormComponent (it is a subclass of FormComponent). A typical scenario in which we may need to implement a custom FormComponentPanel is when our web application and its users wor# with different units of measurement for the same data. To illustrate this possible scenario* letBs consider a form where a user can insert a temperature that will be recorded after being con.erted to Mel.in degrees (see the e,ample proHect (ustom;orm (omponentPanel). The Mel.in scale is wildly adopted among the scientific community and it is one of the se.en base units of the -nternational "ystem of &nits $A* so it ma#es perfect sense to store temperatures e,pressed with this unit of measurement. 9owe.er* in our e.eryday life we still use other temperature scales li#e !elsius or =ahrenheit* so it would be nice to ha.e a component which internally wor#s with Mel.in degrees and automatically applies con.ersion between Mel.in temperature scale and the one adopted by the user. -n order to implement such a component* we can ma#e a subclass of FormComponentPanel and le.erage the con!ert2np"t and on1e0ore)ender methods( in the implementation of the con!ert2np"t method we will con.ert input .alue to Mel.in degrees while in the implementation of on1e0ore)ender method we will ta#e care of con.erting the Mel.in .alue to the temperature scale adopted by the user. @ur custom component will contain two children components( a te,t field to let user insert and edit a temperature .alue and a label to display the letter corresponding to userBs temperature scale (= for =ahrenheit and ! for !elsius). The resulting mar#up file is the following(
<html> <head> </head> <bod"> <Cicket:panel> *egistered temperature: <input siPe89R9 maxlength89R9 Cicket:id89registeredTemperature9/> <label Cicket:id89mesurament0nit9></label> </Cicket:panel> </bod"> </html>

As shown in the mar#up abo.e FormComponentPanel uses the same <Cicket:panel> tag used by Panel to define its mar#up. ow letBs see the Ka.a code of the new form component starting with the on2nitiali3e( method(
public class Temperature+egree3ield extends 3ormComponent#anel<+ouble> pri4ate Text3ield<+ouble> user+egree1 public Temperature+egree3ield7)tring id: super7id:1
36 http%CCen$wikipedia$orgCwikiC nternationalD'ystemDofD@nits

Wicket free user guide

87

1E Wicket forms in detail

& public Temperature+egree3ield7)tring id, $;odel<+ouble> model: super7id, model:1 & !'4erride protected 4oid on$nitialiPe7: super.on$nitialiPe7:1 5bstract*ead'nl";odel<)tring> label;odel8neC 5bstract*ead'nl";odel<)tring>7: !'4erride public )tring get'b2ect7: i%7get/ocale7:.eEuals7/ocale.0):: return 9Y391 return 9YC91 & &1 add7neC /abel79mesurament0nit9, label;odel::1 add7user+egree8neC Text3ield<+ouble>79registeredTemperature9, neC ;odel<+ouble>7:::1 user+egree.setT"pe7+ouble.class:1 &

-nside the on2nitiali3e method we ha.e created a read-only model for the label that displays the letter corresponding to the userBs temperature scale. To determinate which temperature scale is in use* we retrie.e the Locale from the session by calling ComponentBs getLocale( method (we will tal# more about this method in chapter 14). Then* if locale is the one corresponding to the &nited "tates* the chosen scale will be =ahrenheit* otherwise it will be considered as !elsius. -n the final part of on2nitiali3e( we add the two components to our custom form component. 'ou may ha.e noticed that we ha.e e,plicitly set the type of model obHect for the te,t field to double. This is necessary as the starting model obHect is a n"ll reference and this pre.ents the component from automatically determining the type of its model obHect. ow we can loo# at the rest of the code containing the con!ert2np"t and on1e0ore)ender methods(

!'4erride protected 4oid con4ert$nput7: +ouble user+egreeOal 8 user+egree.getCon4erted$nput7:1 +ouble kel4in+egree1 i%7get/ocale7:.eEuals7/ocale.0):: kel4in+egree 8 user+egreeOal > <TS.Z[1 .ig+ecimal bd6el4in 8 neC .ig+ecimal7kel4in+egree:1 .ig+ecimal %raction 8 neC .ig+ecimal7T:.di4ide7neC .ig+ecimal7S::1 kel4in+egree 8 bd6el4in.multipl"7%raction:.doubleOalue7:1 &else kel4in+egree 8 user+egreeOal > =[R.@T1 &

Wicket free user guide

88

1E Wicket forms in detail

setCon4erted$nput7kel4in+egree:1 & !'4erride protected 4oid on.e%ore*ender7: super.on.e%ore*ender7:1 +ouble kel4in+egree 8 7+ouble: get+e%ault;odel'b2ect7:1 +ouble user+egreeOal 8 null1 i%7kel4in+egree 88 null: return1 i%7get/ocale7:.eEuals7/ocale.0):: .ig+ecimal bd6el4in 8 neC .ig+ecimal7kel4in+egree:1 .ig+ecimal %raction 8 neC .ig+ecimal7S:.di4ide7neC .ig+ecimal7T::1 kel4in+egree 8 bd6el4in.multipl"7%raction:.doubleOalue7:1 user+egreeOal 8 kel4in+egree - <TS.Z[1 &else user+egreeOal 8 kel4in+egree - =[R.@T1 & user+egree.set;odel'b2ect7user+egreeOal:1 & &

"ince our component does not directly recei.e the user input* con!ert2np"t( must read this .alue from the inner te,t field using FormComponentBs getCon!erted2np"t( method which returns the input .alue already con.erted to the type specified for the component ( :o"ble in our case). @nce we ha.e the user input we con.ert it to #el.in degrees and we use the resulting .alue to set the con.erted input for our custom component (using method setCon!erted2np"t(/ con!erted2np"t ). <ethod on1e0ore)ender( is responsible for synchroniCing the model of the inner te,tfield with the model of our custom component. To do this we retrie.e the model obHect of the custom component with the get:e0a"ltModel+b5ect( method* then we con.ert it to the temperature scale adopted by the user and finally we use this .alue to set the model obHect of the te,t field.

1/.4 8tateless form


-n chapter A we ha.e seen how 2ic#et pages can be di.ided into two categories( stateful and stateless. Pages that are stateless donBt need to be stored in the user session and they should be used when we donBt need to sa.e any user data in the user session (for e,ample in the public area of a site). Besides sa.ing resources on ser.er-side* stateless pages can be adopted to impro.e user e,perience and to a.oid security wea#nesses. A typical situation where a stateless page can bring these benefits is when we ha.e to implement a login page. =or this #ind of page we might encounter two potential problems if we chose to use a stateful page. The first problem occurs when the user tries to login without a .alid session assigned to him. This could happen if the user lea.es the login page opened for a period of time bigger than the sessionBs timeout and then he decides to log in. &nder these conditions the user will be redirected to a BPage e,piredB error page* which is not e,actly a nice thing for user e,perience. The second problem occurs when a malicious user or a web crawler program attempts to login into our web application* generating a huge number of page .ersions and conseEuently increasing the siCe of the user session.

Wicket free user guide

1%%

1E Wicket forms in detail

To a.oid these #inds of problems we should build a stateless login page which does not depend on a user session. 2ic#et pro.ides a special .ersion of the Form component called StatelessForm which is stateless by default (i.e its method getStatelessHint( returns true)* hence itBs an ideal solution when we want to build a stateless page with a form. A possible implementation of our login form is the following (e,ample proHect Stateless%ogin;orm)( 9tml(
<html> <head> <meta charset89ut%-B9 /> </head> <bod"> <di4>)ession is <b Cicket:id89sessionT"pe9></b></di4> <br/> <di4>T"pe IuserI as correct credentials</di4> <%orm Cicket:id89%orm9> <%ieldset> 0sername: <input t"pe89text9 Cicket:id89username9/> <br/> #assCord: <input t"pe89passCord9 Cicket:id89passCord9/><br/> <input t"pe89submit9/> </%ieldset> </%orm> <br/> <di4 Cicket:id89%eedback#anel9></di4> </bod"> </html>

Ka.a code(
public class Dome#age extends Web#age pri4ate /abel sessionT"pe1 pri4ate )tring passCord1 pri4ate )tring username1 public Dome#age7%inal #age#arameters parameters: )tateless3orm %orm 8 neC )tateless3orm79%orm9: !'4erride protected 4oid on)ubmit7: //sign in i% username and passCord are QuserN i%79user9.eEuals7username: UU username.eEuals7passCord:: in%o790sername and passCord are correctF9:1 else error79Wrong username or passCord9:1 & &1 %orm.add7neC #assCordText3ield79passCord9::1 %orm.add7neC Text3ield79username9::1 add7%orm.set+e%ault;odel7neC Compound#ropert";odel7this:::1 add7sessionT"pe 8 neC /abel79sessionT"pe9, ;odel.o%799:::1

Wicket free user guide

1%1

1E Wicket forms in detail

add7neC 3eedback#anel79%eedback#anel9::1 & !'4erride protected 4oid on.e%ore*ender7: super.on.e%ore*ender7:1 i%7get)ession7:.isTemporar"7:: sessionT"pe.set+e%ault;odel'b2ect79temporar"9:1 else sessionT"pe.set+e%ault;odel'b2ect79permanent9:1 & &

:abel sessionT"pe shows if current session is temporary or not and is set inside on1e0ore)ender( ( if our page is really stateless the session will be always temporary. 2e ha.e also inserted a feedbac# panel in the home page that shows if the credentials are correct. This was done to ma#e the e,ample form more interacti.e.

1/.1/ Working with radio =uttons and check=oxes


-n this paragraph we will see which components can be used to handle 9T<: radio buttons and chec#bo,es. Both these input elements are usually grouped together to display a list of possible choices(

A chec# bo, can be used as single component to set a boolean property. =or this purpose 2ic#et pro.ides the org.apache.wicket.mark"p.html.0orm.Check1o( component which must be attached to <input t"pe89checkbox9.../> tag. -n the ne,t e,ample (proHect Single(heck9o0) we will consider a form similar to the one used in paragraph 8.5 to edit a Person obHect* but with an additional chec#bo, to let the user decide if she wants to subscribe to our mailing list or not. The form uses the following bean as bac#ing obHect(
public class *egistration$n%o implements )erialiPable pri4ate )tring name1 pri4ate )tring surname1 pri4ate )tring address1 pri4ate )tring email1 pri4ate boolean subscribe/ist1 /*-etters and setters*/ &

The mar#up and the code for this e,ample are the following( =ormBs mar#up(
Wicket free user guide

1%4

1E Wicket forms in detail

<%orm Cicket:id89%orm9> <di4 st"le89displa": table19> <di4 st"le89displa": table-roC19> <di4 st"le89displa": table-cell19>Name: </di4> <di4 st"le89displa": table-cell19> <input t"pe89text9 Cicket:id89name9/> </di4> </di4> <di4 st"le89displa": table-roC19> <di4 st"le89displa": table-cell19>)urname: </di4> <di4 st"le89displa": table-cell19> <input t"pe89text9 Cicket:id89surname9/> </di4> </di4> <di4 st"le89displa": table-roC19> <di4 st"le89displa": table-cell19>5ddress: </di4> <di4 st"le89displa": table-cell19> <input t"pe89text9 Cicket:id89address9/> </di4> </di4> <di4 st"le89displa": table-roC19> <di4 st"le89displa": table-cell19>(mail: </di4> <di4 st"le89displa": table-cell19> <input t"pe89text9 Cicket:id89email9/> </di4> </di4> <di4 st"le89displa": table-roC19> <di4 st"le89displa": table-cell19>)ubscribe list:</di4> <di4 st"le89displa": table-cell19> <input t"pe89checkbox9 Cicket:id89subscribe/ist9/> </di4> </di4> </di4> <input t"pe89submit9 4alue89)a4e9/> </%orm>

Page constructor(
public Dome#age7%inal #age#arameters parameters: *egistration$n%o registrtion$n%o 8 neC *egistration$n%o7:1 registrtion$n%o.set)ubscribe/ist7true:1 3orm %orm 8 neC 3orm79%orm9, neC Compound#ropert";odel<*egistration$n%o>7registrtion$n%o::1 %orm.add7neC Text3ield79name9::1 %orm.add7neC Text3ield79surname9::1 %orm.add7neC Text3ield79address9::1 %orm.add7neC Text3ield79email9::1 %orm.add7neC Check.ox79subscribe/ist9::1 add7%orm:1

Wicket free user guide

1%$

1E Wicket forms in detail

&

Please note that the chec#bo, will be initially selected because we ha.e set to true the subscribe flag during the model obHect creation (with instruction registrtion$n%o.set)ubscribe/ist7tr"e:)(

1/.1/.1

Working with grouped check=oxes

2hen we need to display a gi.en number of options with chec#bo,es* we can use the org.apache. wicket.mark"p.html.0orm.Check1o(M"ltipleChoice component. =or e,ample* -f our options are a list of strings* we can display them in this way( 9tml(
<di4 Cicket:id89check-roup9> <input t"pe89checkbox9/>$t Cill be replaced b" the actual checkboxes... </di4>

Ka.a code(
/ist<)tring> %ruits 8 5rra"s.as/ist79apple9, 9straCberr"9, 9Catermelon9:1 %orm.add7neC Check.ox;ultipleChoice79check-roup9, neC /ist;odel<)tring>7neC 5rra"/ist<)tring>7::, %ruits::1

"creenshot of generated page(

This component can be attached to a <di4> tag or to a <span> tag. o specific content is reEuired for this tag as it will be populated with the actual chec#bo,es. "ince this component allows multiple selection* its model obHect is a list. -n the e,ample abo.e we ha.e used model class org.apache. wicket.model."til.ListModel which is specifically designed to wrap a List obHect. By default Check1o(M"ltipleChoice inserts a <br/> tag as suffi, after each option. 2e can configure both the suffi, and the prefi, used by the component with the setPre0i( and setS"00i( methods. 2hen our options are more comple, obHects than simple strings* we can render them using an 2Choice)ender* as we did for :rop:ownChoice in paragraph 8.3( 9tml(
<di4 Cicket:id89check-roup9>

Wicket free user guide

1%3

1E Wicket forms in detail

<input t"pe89checkbox9/>$t Cill be replaced b" actual checkboxes... </di4>

Ka.a code(
#erson 2ohn 8 neC #erson79Lohn9, 9)mith9:1 #erson bob 8 neC #erson79.ob9, 9)mith9:1 #erson 2ill 8 neC #erson79Lill9, 9)mith9:1 /ist<#erson> the)miths 8 5rra"s.as/ist72ohn, bob, 2ill:1 Choice*enderer render 8 neC Choice*enderer79name9:1 %orm.add7neC Check.ox;ultipleChoice79check-roup9, neC /ist;odel<)tring>75rra"/ist<)tring>7::, the)miths, render::1

"creenshot of generated page(

1/.1/.2

How to implement a $8elect all& check=ox

A nice feature we can offer to users when we ha.e a group of chec#bo,es is a FspecialG chec#bo, which selects/unselects all the other options of the group(

2ic#et comes with a couple of utility components that ma#e it easy to implement such a feature. They are Checkbo(M"ltipleChoiceSelector and Check1o(Selector classes* both inside org. apache.wicket.mark"p.html.0orm pac#age. The difference between these two components is that the first wor#s with an instance of Check1o(M"ltipleChoice while the second ta#es in input a list of Check1o( obHects( !hec#bo,<ultiple!hoice"elector usage(
Check.ox;ultipleChoice check-roup1 //check-roup initialiPation... Checkbox;ultipleChoice)elector cbmcs 8 neC Checkbox;ultipleChoice)elector79id9, check-roup:1

!hec#Bo,"elector usage(
Check.ox check.ox@, check.ox=, check.oxR1 //checks initialiPation... Check.ox)elector cbmcs 8 neC Check.ox)elector79id9, check.ox@, check.ox=, check.oxR:1

1/.1/.3

Working with grouped radio =uttons

=or groups of radio buttons we can use the org.apache.wicket.mark"p.html.0orm. )adioChoice component which wor#s in much the same way as Check1o(M"ltipleChoice(

Wicket free user guide

1%5

1E Wicket forms in detail

9tml(
<di4 Cicket:id89radio-roup9> <input t"pe89radio9/>$t Cill be replaced b" actual radio buttons... </di4>

Ka.a code(
/ist<)tring> %ruits 8 5rra"s.as/ist79apple9, 9straCberr"9, 9Catermelon9:1 %orm.add7neC *adioChoice79radio-roup9, ;odel.o%799:, %ruits::1

"creenshot of generated page(

Kust li#e Check1o(M"ltipleChoice* this component pro.ides the setPre0i( and setS"00i( methods to configure the prefi, and suffi, for our options and it supports 2Choice)ender as well. -n addition* )adioChoice pro.ides the want+nSelectionChangedNoti0ications( method to notify the web ser.er when the selected option changes (this is the same method seen for :rop:ownChoice in paragraph 8.3).

1/.11 8electing multiple values with ,ist+ultiple.hoices and Palette


!hec#bo,es wor# well when we ha.e a small amount of options to display* but they Euic#ly become chaotic as the number of options increases. To o.ercome this limit we can use the <select> tag switching it to multiple-choice mode with attribute multiple89multiple9(

ow the user can select multiple options by holding down !trl #ey (or !ommand #ey for <ac) and selecting them. To wor# with multiple choice list 2ic#et pro.ides the org.apache.wicket.mark"p.html.0orm. ListM"ltipleChoice component( 9tml(
<select Cicket:id89%ruits9> <option>choice @</option> <option>choice =</option> </select>

Ka.a code(
/ist<)tring> %ruits 8 5rra"s.as/ist79apple9, 9straCberr"9, 9Catermelon9:1 %orm.add7neC /ist;ultipleChoice79%ruits9, neC /ist;odel<)tring>7neC 5rra"/ist<)tring>7::,

Wicket free user guide

1%A

1E Wicket forms in detail

%ruits::1

"creenshot of generated page(

This component must be bound to a <select> tag but the attribute multiple89multiple9 is not reEuired as it will automatically be added by the component. The number of .isible rows can be set with the setMa()ows(int ma()ows method.

1/.11.1

.omponent Palette

2hile multiple choice list sol.es the problem of handling a big number of multiple choices* it is not much intuiti.e for end users. ThatBs why des#top 0&-s ha.e introduced a more comple, component which can be generally referred to as multi select transfer component (it doesnBt ha.e an actual official name)(

llustration 1E$1% 7n example of multi select transfer component from )asper iAeport This #ind of component is composed by two multiple-choice lists* one on the left displaying the a.ailable options and the other one on the right displaying the selected options. &ser can mo.e options from a list to another by double clic#ing on them or using the buttons placed between the two list. Built-in org.apache.wicket.e(tensions.mark"p.html.0orm.palette.Palette component pro.ides an out-of-the-bo, implementation of a multi select transfer component. -t wor#s in a similar way to ListM"ltipleChoice( 9tml(
<di4 Cicket:id89palette9>

Wicket free user guide

1%6

1E Wicket forms in detail

)elect Cill be replaced b" the actual content... <select multiple89multiple9> <option>option@</option> <option>option=</option> <option>optionR</option> </di4>

Ka.a code(
#erson 2ohn 8 neC #erson79Lohn9, 9)mith9:1 #erson bob 8 neC #erson79.ob9, 9)mith9:1 #erson 2ill 8 neC #erson79Lill9, 9)mith9:1 #erson andrea 8 neC #erson795ndrea9, 9)mith9:1 /ist<#erson> the)miths 8 5rra"s.as/ist72ohn, bob, 2ill, andrea:1 Choice*enderer render 8 neC Choice*enderer79name9:1 %orm.add7neC #alette79palette9, ;odel.o%7neC 5rra"/ist<)tring>7::, neC /ist;odel<)tring> 7the)miths:, render, T, true::1

"creenshot of generated page(

The last two parameters of the PaletteBs constructor (an integer .alue and a boolean .alue) are* respecti.ely* the number of .isible rows for the two lists and a flag to choose if we want to display the two optional buttons which mo.e selected options up and down. The descriptions of the two lists (FA.ailableG and F"electedG) can be customiCed pro.iding two resources with #eys palette.a4ailable and palette.selected. The mar#up of this component uses a number of !"" classes which can be e,tended/o.erriden to customiCe the style of the component. 2e can find these classes and see which tags they decorate in the default mar#up file of the component(
<table cellspacing89A9 cellpadding89=9 class89palette9> <tr> <td class89header header54ailable9><span Cicket:id89a4ailableDeader9>Ha4ailable headerJ</span></td> <td>UX@ZA1</td> <td class89header header)elected9><span Cicket:id89selectedDeader9>Hselected headerJ</span> </td> </tr> <tr> <td class89pane choices9> <select Cicket:id89choices9 class89choices)elect9>HchoicesJ</select>

Wicket free user guide

1%7

1E Wicket forms in detail

</td> <td class89buttons9> <button t"pe89button9 Cicket:id89add.utton9 class89button add9><di4/> </button><br/> <button t"pe89button9 Cicket:id89remo4e.utton9 class89button remo4e9><di4/> </button><br/> <button t"pe89button9 Cicket:id89mo4e0p.utton9 class89button up9><di4/> </button><br/> <button t"pe89button9 Cicket:id89mo4e+oCn.utton9 class89button doCn9><di4/> </button><br/> </td> <td class89pane selection9> <select class89selection)elect9 Cicket:id89selection9>HselectionJ</select> </td> </tr> </table>

1/.12 8ummar
=orms are the standard solution to let users interact with our web applications. -n this chapter we ha.e seen the three steps in.ol.ed with the form processing wor#flow in 2ic#et. 2e ha.e started loo#ing at form .alidation and feedbac# messages generation* then we ha.e seen how 2ic#et con.erts input .alues into Ka.a obHects and .ice .ersa. -n the second part of the chapter we learnt how to build reusable form components and how to implement a stateless form. 2e ha.e ended the chapter with an o.er.iew of the built-in form components needed to handle standard input form elements li#e chec#bo,es* radio buttons and multiple selections lists.

Wicket free user guide

1%8

11 .isplaying multiple items with repeaters

11 0isplaying multiple items with repeaters


A common tas# for web applications is to display a set of items. The most typical scenario where we need such #ind of .isualiCation is when we ha.e to display some #ind of search result. 2ith the old template-based technologies (li#e K"P) we used to accomplish this tas# using classic 0or or while loops(
<html> <head> <meta http-eEui489Content-T"pe9 content89text/html1 charset80T3-B9> <title>$nsert title here</title> </head> <bod"> <K %or7int i 8 @=1 i<8R=1 i>>: K> <di4>DelloF $Im index nY<K8 K></di4> <K & K> </bod">

To ease this tas# 2ic#et pro.ides a number of special-purpose components called repeaters which are designed to use their related mar#up to display the items of a gi.en set in a more natural and less chaotic way. -n this chapter we will see some of the built-in repeaters that come with 2ic#et.

11.1 .omponent 3epeatingEiew


!omponent org.apache.wicket.mark"p.repeater.)epeating-iew is a container which renders its children components using the tag it is bound to. -t can contain an arbitrary number of children elements and we can obtain a new .alid id for a new child calling its method newChild2d( . This component is particularly suited when we ha.e to repeat a simple mar#up fragment* for e,ample when we want to display some items as a 9T<: list( 9tml(
<ul> <li Cicket:id89list$tems9></li> </ul>

Ka.a code(
*epeatingOieC list$tems 8 neC *epeatingOieC79list$tems9:1 list$tems.add7neC /abel7list$tems.neCChild$d7:, 9green9:1 list$tems.add7neC /abel7list$tems.neCChild$d7:, 9blue9:1 list$tems.add7neC /abel7list$tems.neCChild$d7:, 9red9:1

Wicket free user guide

11%

11 .isplaying multiple items with repeaters

0enerated mar#up(
<ul> <li>green</li> <li>blue</li> <li>red</li> </ul>

As we can see in this e,ample* each child component has been rendered using the parent mar#up as if it was its own.

11.2 .omponent ,istEiew


As its name suggests* component org.apache.wicket.mark"p.html.list.List-iew is designed to display a gi.en list of obHects which can be pro.ided as a standard Ka.a List or as a model containing the concrete List. List-iew iterates o.er the list and creates a child component of class org.apache.wicket.mark"p.html.list.List2tem for e.ery encountered item. &nli#e )epeating-iew this component is intended to be used with comple, mar#up fragments containing nested components. To generate its children* List-iew calls its abstract method pop"late2tem(List2tem7/8 item for each item in the list* so we must pro.ide an implementation of this method to tell the component how to create its children components. -n the following e,ample we use a List-iew to display a list of Person obHects( 9tml(
... <bod"> <di4 id89bd9 st"le89displa": table19> <di4 Cicket:id89persons9 st"le89displa": table-roC19> <di4 st"le89displa": table-cell19><b>3ull name: </b></di4> <di4 Cicket:id89%ullName9 st"le89displa": table-cell19></di4> </di4> </di4> </bod"> ...

Ka.a code (page constructor)(


public Dome#age7%inal #age#arameters parameters: /ist<#erson> persons 8 5rra"s.as/ist7neC #erson79Lohn9, 9)mith9:, neC #erson79+an9, 9Wong9::1 add7neC /istOieC<#erson>79persons9, persons: !'4erride protected 4oid populate$tem7/ist$tem<#erson> item: item.add7neC /abel79%ullName9, neC #ropert";odel7item.get;odel7:, 9%ullName9:::1 & &:1 &

"creenshot of generated page(

Wicket free user guide

111

11 .isplaying multiple items with repeaters

-n this e,ample we ha.e displayed the full name of two PersonBs instances. The most interesting part of the code is the implementation of method pop"late2tem where parameter item is the current child component created by List-iew and its model contains the corresponding element of the list. Please note that inside pop"late2tem we must add nested components to item obHect and not directly to the List-iew.

11.2.1

,istEiew and Horm

By default List-iew replaces its children components with new instances e.ery time is rendered. &nfortunately this beha.ior is a problem if List-iew is inside a form and it contains form components. The problem is caused by the fact that children components are replaced by new ones before form is rendered* hence they canBt #eep their input .alue if .alidation fails and* furthermore* their feedbac# messages can not be displayed. To a.oid this #ind of problem we can force List-iew to reuse its children components using its method set)e"se2tems and passing tr"e as parameter. -f for any reason we need to refresh children components after we ha.e in.o#ed set)e"se2tems(tr"e * we can use Mark"pContainer#s method remo!eAll( to force List-iew to rebuild them.

11.3 .omponent 3efreshingEiew


!omponent org.apache.wicket.mark"p.repeater.)e0reshing-iew is a subclass of )epeating-iew that comes with a customiCable rendering strategy for its children components. )e0reshing-iew defines abstract methods pop"late2tem(2tem and get2temModels( . The first method is similar to the namesa#e method seen for List-iew* but it ta#es in input an instance of class org.apache.wicket.mark"p.repeater.2tem which is a subclass of List2tem. )e0reshing-iew is designed to display a collection of models containing the actual items. An iterator o.er these models is returned by the other abstract method get2temModels. The following code is a .ersion of the pre.ious e,ample that uses )e0reshing-iew in place of List-iew( 9tml(
... <bod"> <di4 id89bd9 st"le89displa": table19> <di4 Cicket:id89persons9 st"le89displa": table-roC19> <di4 st"le89displa": table-cell19><b>3ull name: </b></di4> <di4 Cicket:id89%ullName9 st"le89displa": table-cell19></di4> </di4> </di4> </bod"> ...

Ka.a code (page constructor)(


public Dome#age7%inal #age#arameters parameters: //de%ine the list o% models to use %inal /ist<$;odel<#erson>> persons 8 neC 5rra"/ist<$;odel<#erson>>7:1

Wicket free user guide

114

11 .isplaying multiple items with repeaters

persons.add7;odel.o%7neC #erson79Lohn9, 9)mith9::1 persons.add7;odel.o%7neC #erson79+an9, 9Wong9::1 add7neC *e%reshingOieC<#erson>79persons9: !'4erride protected 4oid populate$tem7$tem<#erson> item: item.add7neC /abel79%ullName9, neC #ropert";odel7item.get;odel7:, 9%ullName9:::1 & !'4erride protected $terator<$;odel<#erson>> get$tem;odels7: return persons.iterator7:1 & &:1 &

11.3.1

!tem reuse strateg

By default* Hust li#e List-iew* )e0reshing-iew replaces its children with new instances e.ery time is rendered. The strategy that decides if and how children components must be refreshed is returned by method get2tem)e"seStrateg,. This strategy is an implementation of interface 22tem)e"seStrateg,. The default implementation used by )e0reshing-iew is class :e0a"lt2tem)e"seStrateg, but 2ic#et pro.ides also strategy )e"se20Models'6"alStrateg, which reuses an item if its model has been returned by the iterator obtained with method get2temModels. To set a custom strategy we must use method set2tem)e"seStrateg,.

11.# Pagea=le repeaters


2ic#et offers a number of components that should be used when we ha.e to display a big number of items (for e,ample the results of a select "Q: Euery). All these components implements interface org.apache.wicket.mark"p.html.na!igation. paging.2Pageable and use interface 2:ataPro!ider (placed in pac#age org.apache.wicket. mark"p.repeater.data) as data source. This interface is designed to support data paging. 2e will see an e,ample of data paging later in paragraph 11.3.4. The methods defined by 2:ataPro!ider are the following( iteratorJlong firstG long count@( returns an iterator o.er a subset of the entire dataset. The subset starts from the item at position %irst and includes all the ne,t count items (i.e. itBs the closed inter.al V%irst*%irstNcountW). si6eJ@( gets the siCe of the entire dataset. modelJ* o=<ect@( this method is used to wrap an item returned by the iterator with a model. This can be necessary if* for e,ample* we need to wrap items with a detachable model to pre.ent them from being serialiCed. 2ic#et already pro.ides implementations of 2:ataPro!ider to wor# with a List as data source (List:ataPro!ider) and to support data sorting (Sortable:ataPro!ider).

11.#.1

.omponent 5ataEiew

!lass org.apache.wicket.mark"p.repeater.data.:ata-iew is the simplest pageable repeater shipped with 2ic#et. :ata-iew comes with abstract method pop"late2tem(2tem that must be implemented to configure children components. -n the following e,ample we use a :ata-iew to display a list of Person obHects in a 9T<: table(
Wicket free user guide

11$

11 .isplaying multiple items with repeaters

9tml(
<table> <tr> <th>Name</th><th>)urename</th><th>5ddress</th><th>(mail</th> </tr> <tr Cicket:id89roCs9> <td Cicket:id89data*oC9></td> </tr> </table>

Ka.a code(
//method load#ersons is de%ined elseChere /ist<#erson> persons 8 load#ersons7:1 /ist+ata#ro4ider<#erson> list+ata#ro4ider 8 neC /ist+ata#ro4ider<#erson>7persons:1 +ataOieC<#erson> dataOieC 8 neC +ataOieC<#erson>79roC9, list+ata#ro4ider: !'4erride protected 4oid populate$tem7$tem<#erson> item: #erson person 8 item.get;odel'b2ect7:1 *epeatingOieC repeatingOieC 8 neC *epeatingOieC79data*oC9:1 repeatingOieC.add7neC /abel7repeatingOieC.neCChild$d7:, person.getName7:::1 repeatingOieC.add7neC /abel7repeatingOieC.neCChild$d7:, person.get)urename7:::1 repeatingOieC.add7neC /abel7repeatingOieC.neCChild$d7:, person.get5ddress7:::1 repeatingOieC.add7neC /abel7repeatingOieC.neCChild$d7:, person.get(mail7:::1 item.add7repeatingOieC:1 & &1 add7dataOieC:1

Please note that in the code abo.e we ha.e used also a )epeating-iew component to populate the rows of the table. -n the ne,t paragraph we will see a similar e,ample that adds support for data paging.

11.#.2

5ata paging

To enable data paging on a pageable repeaters* we must first set the number of items to display per page with method set2temsPerPage(long items . Then* we must attach the repeater to panel PagingNa!igator (placed in pac#age org.apache.wicket.mark"p.html.na!igation .paging) which is responsible for rendering a na.igation bar containing the lin#s illustrated in the following picture(

ProHect Page@ata6iew#0ample mi,es a :ata-iew component with a PagingNa!igator to display the list of all countries of the world sorted by alphabetical order $6. 9ere is the initialiCation code of the proHect home page(

37 The list of countries is read from a csv file downloaded from http: opengeocode.org download cow.php

Wicket free user guide

113

11 .isplaying multiple items with repeaters

9tml(
<table> <tr> <th>$)' R@ZZ-@</th><th>Name</th><th>/ong name</th><th>Capital</th><th>#opulation</th> </tr> <tr Cicket:id89roCs9> <td Cicket:id89data*oC9></td> </tr> </table>

Ka.a code(
public Dome#age7%inal #age#arameters parameters: super7parameters:1 //method loadCountries3romCs4 is de%ined elseChere in the class. //$t reads countries data %rom a cs4 %ile and returns each roC as an arra" o% )trings. /ist<)tringHJ> countries 8 loadCountries3romCs47:1 /ist+ata#ro4ider<)tringHJ> list+ata#ro4ider 8 neC /ist+ata#ro4ider<)tringHJ>7countries:1 +ataOieC<)tringHJ> dataOieC 8 neC +ataOieC<)tringHJ>79roCs9, list+ata#ro4ider: !'4erride protected 4oid populate$tem7$tem<)tringHJ> item: )tringHJ countries5rr 8 item.get;odel'b2ect7:1 *epeatingOieC repeatingOieC 8 neC *epeatingOieC79data*oC9:1 %or 7int i 8 A1 i < countries5rr.length1 i>>: repeatingOieC.add7neC /abel7repeatingOieC.neCChild$d7:, countries5rrHiJ::1 & item.add7repeatingOieC:1 & &1 dataOieC.set$tems#er#age7@T:1 add7dataOieC:1 add7neC #agingNa4igator79pagingNa4igator9, dataOieC::1 &

The data of a single country (-"@ code* name* long name* capital and population) are handled with an array of strings. The usage of PagingNa!igator itBs Euite straightforward as we need to simply pass the pageable repeater to its constructor. To e,plore the other pageable repeaters shipped with 2ic#et you can .isit the page at http(//www.wic#et-library.com/wic#et-e,amples/repeater/ where you can find li.e e,amples of these components. >ote 2ic#et pro.ides also component PageableList-iew which is a sublcass of List-iew that implements interface 2Pageable* hence it can be considered a pageable repeaters e.en if it doesnBt use interface 2:ataPro!ider as data source.

11.( 8ummar

Wicket free user guide

115

11 .isplaying multiple items with repeaters

-n this chapter we ha.e e,plored the built-in set of components called repeaters which are designed to repeat their own mar#up in output to display a set of items. 2e ha.e started with component )epeating-iew which can be used to repeat a simple mar#up fragment. Then* we ha.e seen components List-iew and )e0reshing-iew which should be used when the mar#up to repeat contains nested components to populate. =inally* we ha.e discussed those repeaters that support data paging and that are called pageable repeaters. 2e ended the chapter loo#ing at an e,ample where a pageable repeater is used with panel PagingNa!igator to ma#e its dataset na.igable by the user.

Wicket free user guide

11A

1* nternationali<ation with Wicket

Internationali1ation with Wicket

-n chapter 1% we ha.e seen how the topic of localiCation is in.ol.ed in the generation of feedbac# messages and we had a first contact with resource bundles. -n this chapter we will continue to e,plore the localiCation support pro.ided by 2ic#et and we will learn how to build pages and components ready to be localiCed in different languages.

12.1 ,ocali6ation
As we ha.e seen in chapter 1%* the infrastructure of feedbac# messages is built on top of Ka.a internationaliCation (i17n) support* so it should not be surprising that the same infrastructure is used also for localiCation purpose. 9owe.er* while so far we ha.e used only the A$pplication(lass)ameB.properties file to store our custom messages* in this chapter we will see that also pages* components* .alidators and e.en Ka.a pac#ages can ha.e their own resource bundles. This allows us to split bundles into multiple files #eeping them close to where they are used. But before di.ing into the details of internationaliCation with 2ic#et* itBs worthwhile to Euic#ly re.iew how i17n wor#s under Ka.a* see what classes are in.ol.ed and how they are integrated into 2ic#et. >ote Pro.iding a full description of Ka.a support for i17n is clearly out of the scope of this document. -f you need more informations about this topic you can find them in the Ka.aDocs and in the official i17n tutorial $7.

12.2 .lass ,ocale and 3esource;undle


!lass 5a!a."til.Locale represents a specific country or language of the world and is used in Ka.a to retrie.e other locale-dependent informations li#e numeric and date formats* the currency in use in a country and so on. "uch #ind of informations are accessed through special entities called resource bundles which are implemented by class 5a!a."til.)eso"rce1"ndle. I.ery resource bundle is identified by a full name which is built using four parameters( a base name (which is reEuired)* a language code* a country code and a variant (which are all optional). These three optional parameters are pro.ided by an instance of Locale with its three corresponding getter methods( getLang"age( * getCo"ntr,( and get-ariant( . Parameter language code is a lowercase -"@ A$8 4-letter code (li#e 3h for !hinese* de for 0erman and so on) while country code is an uppercase -"@ $1AA 4-letter code (li#e CN for !hina* :' for 0ermany and so on). The final full name will ha.e the following structure ( @TI( to#ens inside sEuared brac#ets are optional)(
<base name>HM<language code>HM<C'0NT*GMC'+(>HM<4ariant code>JJJ

=or e,ample a bundle with M,1"ndle as base name and localiCed for <andarin !hinese (language code 3h* country code CH* .ariant cmn) will ha.e M,1"ndleG3hGCHGcmn as full name.
38 http: docs.oracle.com -avase tutorial i>?n inde0.html

Wicket free user guide

116

1* nternationali<ation with Wicket

A base name can be a fully Eualified class name* meaning that it can include a pac#age name before the actual base name. The specified pac#age will be the container of the gi.en bundle. =or e,ample if we use org.0oo.M,1"ndle as base name* the bundle named M,1"ndle will be searched inside pac#age org.0oo. The actual base name (M,1"ndle in our e,ample) will be used to build the full name of the bundle following the same rules seen abo.e. )eso"rce1"ndle is an abstract factory class* hence it e,poses a number of factory methods named get1"ndle to load a concrete bundle. 2ithout going into too much details we can say that a bundle corresponds to a file in the classpath. To find a file for a gi.en bundle* get1"ndle needs first to generate an ordered list of candidate bundle names. These names are the set of all possible full names for a gi.en bundle. =or e,ample if we ha.e org.0oo.M,1"ndle as base name and the current locale is the one seen before for <andarin !hinese* the candidate names will be( 1. org.0oo.M,1"ndleG3hGCHGcmn 2. org.0oo.M,1"ndleG3hGCH 3. org.0oo.M,1"ndleG3h 4. org.0oo.M,1"ndle The list of these candidate names is generated starting from the most specific one and subtracting an optional parameter at each step. The last name of the list corresponds to the default resource bundle which is the most general name and is eEual to the base name. @nce that get1"ndle has generated the list of candidate names* it will iterate o.er them to find the first one for which is possible to load a class or a properties file. The class must be a subclass of )eso"rce1"ndle ha.ing as class name the full name used in the current iteration. -f such a class is not found* get1"ndle will try to locate a properties file ha.ing a file name eEuals to the current full name (Ka.a will automatically append e,tension .properties to the full name). =or e,ample gi.en the resource bundle of the pre.ious e,ample* Ka.a will search first for class org.0oo.M,1"ndleG3hGCHGcmn and then for file M,1"ndleG3hGCHGcmn.properties inside pac#age org.0oo. -f no file is found for any of the candidate names* a Missing)eso"rce'(ception will be thrown. Bundles contains local-dependent string resources identified by a #ey that is uniEue in the gi.en bundle. "o once we ha.e obtained a .alid bundle we can access these obHects with method getString (String ke, . As we ha.e seen before wor#ing with feedbac# messages* in 2ic#et most of the times we will wor# with properties files rather than with bundle classes. -n chapter 1% we used a properties file ha.ing as base name the class name of the application class and without any information about the locale. This file is the default resource bundle for a 2ic#et application. -n paragraph 14.3 we will e,plore the algorithm used in 2ic#et to locate the a.ailable bundles for a gi.en component. @nce we ha.e learnt how to le.erage this algorithm* we will be able to split our bundles into more files organiCed in a logical hierarchy.

12.3 ,ocali6ation in Wicket


A component can get the current locale in use calling its method getLocale( . By default this method will be recursi.ely called on componentBs parent containers until one of them returns a .alid locale. -f no one of them returns a locale* this method will get the one associated with the current user session. This locale is automatically generated by 2ic#et in accordance with the language settings of the browser. De.elopers can change the locale of the current session with SessionBs method setLocale (Locale locale (
)ession.get7:.set/ocale7locale:

Wicket free user guide

117

1* nternationali<ation with Wicket

12.3.1

)t le and variation parameters for =undles

-n addition to localeBs informations* 2ic#et supports two further parameters to identify a resource bundle( style and variation. Parameter style is a string .alue and is defined at session-le.el. To set/get the style for the current session we can use the corresponding setter and getter of class Session(
)ession.get7:.set)t"le79m")t"le9:1 )ession.get7:.get)t"le7:1

-f set* styleBs .alue contributes to the final full name of the bundle and it is placed between the base name and the localeBs informations(
<base name>HMst"leJHM<language code>HM<C'0NT*GMC'+(>HM<4ariant code>JJJ

2ic#et gi.es the priority to candidate names containing the style information (if a.ailable). The other parameter we can use for localiCation is variation. Kust li#e style also variation is a string .alue* but it is defined at component-le.el. The .alue of .ariation is returned by ComponentBs method get-ariation( . By default this method returns the .ariation of the parent component or a n"ll .alue if a component hasnBt a parent (i.e. itBs a page). -f we want to customiCe this parameter we must o.erwrite method get-ariation and ma#e it return the desired .alue. DariationBs .alue contributes to the final full name of the bundle and is placed before style parameter(
<base name>HM4ariationJHMst"leJHM<language code>HM<C'0NT*GMC'+(>HM<4ariant code>JJJ

12.3.2

0sing 9+, files as resource =undles

Ka.a uses the standard character set -"@ 7758-1 $8 to encode te,t files li#e properties files. &nfortunately -"@ 7758-1 does not support most of the e,tra-Iuropean languages li#e !hinese or Kapanese. The only way to use properties files with such languages is to use escaped &nicode characters3%* but this leads to not human-readable files. =or e,ample if we wanted to write the word BwebsiteB in simplified !hinese (the ideograms are ) we should write the &nicode characters \u[3T@\u[5+S. ThatBs why starting from .ersion 1.5* Ka.a introduced the support for L<: files as resource bundles. L<: files are generally encoded with character sets &T=-7 or &T=-1A which support e.ery symbol of the &nicode standard. -n order to be a .alid resource bundle the L<: file must conform to the DTD a.ailable at http(//Ha.a.sun.com/dtd/properties.dtd. 9ere is an e,ample of L<: resource bundle ta#en from proHect %ocali<edCreetings (file WicketApplicationG3h.properties.(ml) containing the translation in simplified !hinese of the greeting message F2elcome to the website;G(
<?xml 4ersion89@.A9 encoding890T3-B9?> <F+'CTG#( properties )G)T(; 9http://2a4a.sun.com/dtd/properties.dtd9> <properties> <entr" ke"89greeting;essage9></entr"> </properties>

To use L<: bundles in 2ic#et we donBt need to put in place any additional configuration. The only rule we ha.e to respect with these files is to use properties.(ml as e,tension while their base name
39 http: en.wikipedia.org wiki IS2 I#(1??DE*> 40 http: en.wikipedia.org wiki %ist1of1:nicode1characters

Wicket free user guide

118

1* nternationali<ation with Wicket

follows the same rules seen so far for bundle names.

12.3.3

3eading =undles from code

!lass Component ma#es reading bundles .ery easy with method getString(String ke, . This method searches for a resource with the gi.en #ey loo#ing into the resource bundles .isited by the loo#up algorithm illustrated in paragraph 14.3. =or e,ample if we ha.e a greeting message with #ey greetingMessage in our applicationBs resource bundle* we can read it from our component code with this instruction(
get)tring79greeting;essage9:1

12.3.#

,ocali6ation of =undles in Wicket.

-n chapter 1% we ha.e used as resource bundle the properties file placed ne,t to our application class. This file is the default resource bundle for the entire application and it is used by the loo#up algorithm if it doesnBt find any better match for a gi.en component and locale. -f we want to pro.ide localiCed .ersions of this file we must simply follow the rules of Ka.a i17n and put our translated resources into another properties file with a name corresponding to the desired locale. =or e,ample proHect %ocali<edCreetings comes with the default applicationBs properties file ( WicketApplication.properties) containing a greeting message(
greeting;essage8Welcome to the siteF

Along with this file we can also find a bundle for 0erman ( WicketApplicationGde.properties) and another one in L<: format for simplified !hinese (WicketApplicationG3h.properties.(ml). The e,ample proHect consists of a single page ( HomePage.5a!a) displaying the greeting message. The current locale can be changed with a drop-down list and the possible options are Inglish (the default one)* 0erman and simplified !hinese(

llustration 1*$1% The home page of pro#ect 0ocali<edGreetings locali<ed in German The label displaying the greeting message has a custom read-only model which returns the message with method getString. The initialiCation code for this label is this(
5bstract*ead'nl";odel<)tring> model 8 neC 5bstract*ead'nl";odel<)tring>7: !'4erride public )tring get'b2ect7: return get)tring79greeting;essage9:1 & &1 add7neC /abel79greeting;essage9, model::1

Wicket free user guide

14%

1* nternationali<ation with Wicket

!lass org.apache.wicket.model.Abstract)ead+nl,Model is a con.enience class for implementing read-only models. -n this proHect we ha.e implemented a custom read-only model for illustrati.e purposes only because 2ic#et already pro.ides built-in models for the same tas#. 2e will see them in paragraph 14.A. The rest of the code of the home page builds the stateless form and the drop-down menu used to change the locale.
/ist</ocale> locales 8 5rra"s.as/ist7/ocale.(N-/$)D, /ocale.CD$N()(, /ocale.-(*;5N:1 %inal +rop+oCnChoice</ocale> change/ocale 8 neC +rop+oCnChoice</ocale>79change/ocale9, neC ;odel</ocale>7:, locales:1 )tateless3orm %orm 8 neC )tateless3orm79%orm9: !'4erride protected 4oid on)ubmit7: )ession.get7:.set/ocale7change/ocale.get;odel'b2ect7::1 & &1 set)tatelessDint7true:1 add7%orm.add7change/ocale::

12.3.(

,ocali6ation of markup files

Although resource bundles e,ist to e,tract local-dependent elements from our code and from &components* in 2ic#et we can decide to pro.ide different mar#up files for different locale settings. Kust li#e standard mar#up files* by default localiCed mar#up files must be placed ne,t to componentBs class and their file name must contain the localeBs informations. -n the following picture* C"stomPanel comes with a standard (or default) mar#up file and with another one localiCed for 0erman(

llustration 1*$*% Component with markup locali<ed in German 2hen the current locale corresponds to 0erman country (language code de)* mar#up file !ustomPanelOde.html will be used in place of the default one.

12.3.-

3eading =undles with tag <wicket:messa!e>


<Cicket:message>.

"tring resources can be also retrie.ed directly from mar#up code using tag of the desired resource is specified with attribute ke"(

The #ey

<Cicket:message ke"89greeting;essage9>message goes here</Cicket:message>

can be adopted also to localiCe the attributes of a tag. The name of the attribute and the resource #ey are e,pressed as a colon-separated .alue. -n the following mar#up the content of attribute 4alue will be replaced with the localiCed resource ha.ing Bke"<4alueB as #ey(
Cicket:message
Wicket free user guide

141

1* nternationali<ation with Wicket

<input t"pe89submit9 4alue89#re4ieC 4alue9 Cicket:message894alue:ke"<4alue9/>

-f we want to specify multiple attributes at once* we can separate them with a coma(
<input t"pe89submit9 4alue89#re4ieC 4alue9 Cicket:message894alue:ke"<4alue,title:ke"<title9/>

12.# ;undles lookup algorithm


As we hinted at the beginning of this chapter* by default 2ic#et pro.ides a .ery fle,ible algorithm to locate the resource bundles a.ailable for a gi.en component. -n this paragraph we will learn how this default loo#up algorithm wor#s and which options it offers to manage our bundle files.

12.#.1

,ocali6ing pages and panels

"imilarly to application class* also component classes can ha.e their own bundle files ha.ing as base name the class name of the related component and placed in the same pac#age. "o for e,ample if class C"stomPanel is a custom panel we created* we can pro.ide it with a default bundle file called C"stomPanel.properties containing the te,tual resources used by this panel. This rule applies to page classes as well(

llustration 1*$1% Page and panel with their own bundle @ne fundamental thing to #eep in mind when we wor# with these #inds of bundles is that the loo#up algorithm gi.es priority to the bundles of the containers of the component that is reEuesting a localiCed resource. The more a container is higher in the hierarchy* the bigger is its priority o.er the other components. This mechanism was made to allow containers to o.erwrite resources used by children components. As a conseEuence the .alues inside the resource bundle of a page will ha.e the priority o.er the other .alues with the same #ey defined in the bundles of children components. To better grasp this concept letBs consider the component hierarchy depicted in the following picture(

llustration 1*$3% The bundle of CustomPanel is overwritten by the one of CustomPage$

Wicket free user guide

144

1* nternationali<ation with Wicket

-f C"stomPanel tries to retrie.e the string resource ha.ing B messageB as #ey* it will get the .alue and not the one defined inside its own bundle file. The default message-loo#up algorithm is not limited to component hierarchy but it also includes the class hierarchy of e.ery component .isited in the search strategy described so far. This ma#es bundle files inheritable* Hust li#e mar#up files. 2hen the hierarchy of a container component is e,plored* any ancestor has the priority o.er children components. !onsider for e,ample the hierarchy in the following picture(
IWellcomeFI

llustration 1*$9% The bundle of CustomPanel is overwritten by the one of page class BasePage$

"imilarly to the pre.ious e,ample* the bundle owned by C"stomPanel is o.erwritten by the bundle of page class 1asePage (which has been inherited by C"stomPage).

12.#.2

.omponent?specific resources

-n order to ma#e a resource specific for a gi.en child component* we can prefi, the message #ey with the id of the desired component. !onsider for e,ample the following code and bundle of a generic page( Page code(
add7neC /abel79label9,neC *esource;odel79labelOalue9:::1 add7neC /abel79another/abel9,neC *esource;odel79labelOalue9:::1

Page bundle(
labelOalue8+e%ault 4alue another/abel.labelOalue8Oalue %or another/abel

:abel with id another/abel will display the .alue IOalue %or another/abelI while label label will display -n a similar fashion* parent containers can specify a resource for a nested child component prepending also its relati.e path (the path is dot-separated)(
I+e%ault 4alueI.

Page code(
Wicket free user guide

14$

1* nternationali<ation with Wicket

3orm %orm 8 neC 3orm79%orm9:1 %orm.add7neC /abel79another/abel9,neC *esource;odel79labelOalue9:::1 add7%orm:1

Page bundle(
labelOalue8+e%ault 4alue another/abel.labelOalue8Oalue %or another/abel %orm.another/abel.labelOalue8Oalue %or another/abel inside %orm

2ith the code and the bundle abo.e* the label inside the form will display the .alue
another/abel inside %ormI.

IOalue %or

12.#.3

Package =undles

-f no one of the pre.ious steps can find a resource for the gi.en #ey* the algorithm will loo# for package bundles. These bundles ha.e package as base name and they can be placed in one of the pac#age of our application(

llustration 1*$8% Package bundles in each package of the application Pac#ages are tra.ersed starting from the one containing the component reEuesting for a resource and going up to the root pac#age.

12.#.#

;undles for feed=ack messages

The algorithm described so far applies to feedbac# messages as well. -n case of .alidation errors* the component that has caused the error will be considered as the component which the string resource is relati.e to. =urthermore* Hust li#e application class and components* .alidators can ha.e their own bundles placed ne,t to their class and ha.ing as base name their class name. This allows us to distribute .alidators along with the messages they use to report errors(

llustration 1*$2% Ialidator with its own bundle

Wicket free user guide

143

1* nternationali<ation with Wicket

DalidatorBs resource bundles ha.e the lowest priority in the loo#up algorithm. They can be o.erwritten by resource bundles of components* pac#ages and application class.

12.#.(

Dxtending the default lookup algorithm

2ic#et implements the default loo#up algorithm using the strategy patternF>. The concrete strategies are abstracted with the interface org.apache.wicket.reso"rce.loader.2String)eso"rce Loader. By default 2ic#et uses the following implementations of 2String)eso"rceLoader (sorted by e,ecution order)( 1. .omponent8tring3esource,oader( implements most of the default algorithm. -t searches for a gi.en resource across bundles from the container hierarchy* from class hierarchy and from the gi.en component. 4. Package8tring3esource,oader( searches into pac#age bundles. $. .lass8tring3esource,oader( searches into bundles of a gi.en class. By default the target class is the application class. 3. Ealidator8tring3esource,oader( searches for resources into .alidatorBs bundles. A list of .alidators is pro.ided by the form component that failed .alidation. 5. !nitiali6er8tring3esource,oader( this resource allows internationaliCation to interact with the initialiCation mechanism of the framewor# that will be illustrated in paragraph 15.3. De.eloper can customiCe loo#up algorithm remo.ing default resource loaders or adding custom implementations to the list of the resource loaders in use. This tas# can be accomplished using method getString)eso"rceLoaders of setting interface org.apache.wicket.settings. 2)eso"rceSettings(
!'4erride public 4oid init7: super.init7:1 //retrie4e $*esource)ettings and then the list o% resource loaders /ist<$)tring*esource/oader> resource/oaders8 get*esource)ettings7:. get)tring*esource/oaders7:1 //customiPe the list...

12.( ,ocali6ation of componentAs choices


!omponents that inherit from AbstractChoice (such as :rop:ownChoice* Check1o(M"ltiple Choice and )adioChoice) must o.erride method locali3e:ispla,-al"es and ma#e it return tr"e to localiCe the .alues displayed for their choices. By default this method return 0alse so .alues are displayed as they are. @nce localiCation is acti.ated we can use display .alues as #ey for our localiCed string resources. -n proHect %ocali<ed(hoices#0ample we ha.e a drop-down list that displays four colors (green* red* blue* and yellow) which are localiCed in three languages (Inglish* 0erman and -talian). The current locale can be changed with another drop-down menu (in a similar fashion to proHect %ocali<edCreetings). The code of the home page and the relati.e bundles are the following( Ka.a code(
public Dome#age7%inal #age#arameters parameters: super7parameters:1
41 http: en.wikipedia.org wiki Strategy1pattern

Wicket free user guide

145

1* nternationali<ation with Wicket

/ist</ocale> locales 8 5rra"s.as/ist7/ocale.(N-/$)D, /ocale.$T5/$5N, /ocale.-(*;5N:1 /ist<)tring> colors 8 5rra"s.as/ist79green9, 9red9, 9blue9, 9"elloC9:1 %inal +rop+oCnChoice</ocale> change/ocale 8 neC +rop+oCnChoice</ocale>79change/ocale9, neC ;odel</ocale>7:, locales:1 )tateless3orm %orm 8 neC )tateless3orm79%orm9: !'4erride protected 4oid on)ubmit7: )ession.get7:.set/ocale7change/ocale.get;odel'b2ect7::1 & &1 +rop+oCnChoice<)tring> selectColor 8 neC +rop+oCnChoice<)tring>79selectColor9, neC ;odel<)tring>7:, colors: !'4erride protected boolean localiPe+ispla"Oalues7: return true1 & &1 %orm.add7selectColor:1 add7%orm.add7change/ocale::1 &

Default bundle (Inglish)(


selectColor.null8)elect a color green8-reen red8*ed blue8.lue "elloC8GelloC

0erman bundle(
selectColor.null8Wahlen sie eine %arbe green8-run red8*ot blue8.lau "elloC8-elb

-talian bundle(
selectColor.null8)cegli un colore green8Oerde red8*osso blue8.lu "elloC8-iallo

Along with the localiCed .ersions of colors names* in the bundles abo.e we can also find a custom .alue for the placeholder te,t (F!hose one G) used for n"ll .alue. The resource #ey for this resource is InullI or I<component id>.nullI if we want to ma#e it component-specific.

12.- !nternationali6ation and +odels


Wicket free user guide

14A

1* nternationali<ation with Wicket

-nternationaliCation is another good chance to taste the power of models. 2ic#et pro.ides two built-in models to better integrate our components with string resources( they are )eso"rceModel and String)eso"rceModel.

12.-.1

3esource+odel

<odel org.apache.wicket.model.)eso"rceModel acts Hust li#e the read-only model we ha.e implemented in paragraph 14.$.3. -t simply retrie.es a string resource corresponding to a gi.en #ey(
//build a *esource;odel %or ke" Igreeting;essageI neC *esource;odel79greeting;essage9:1

2e can also specify a default .alue to use if the reEuested resource is not found(
//build a *esource;odel Cith a de%ault 4alue neC *esource;odel79not(xisting*esource9, 9*esource not %ound.9:1

12.-.2

8tring3esource+odel

<odel org.apache.wicket.model.String)eso"rceModel allows to wor# with comple, and dynamic string resources containing parameters and property e,pressions. The basic constructor of this model ta#es in input a resource #ey and another model. This further model can be used by both the #ey and the related resource to specify dynamic .alues with property e,pressions. =or e,ample letBs say that we are wor#ing on an e-commerce site which has a page where users can see an o.er.iew of their orders. To handle the state of userBs orders we will use the following bean and enum (the code is from proHect String"esource4odel#0ample)( Bean(
public class 'rder implements )erialiPable pri4ate +ate order+ate1 pri4ate '*+(*M)T5T0) status1 public 'rder7+ate order+ate, '*+(*M)T5T0) status: super7:1 this.order+ate 8 order+ate1 this.status 8 status1 & //-etters and setters %or pri4ate %ields &

Inum(
public enum '*+(*M)T5T0)

#5G;(NTM5CC(#T(+7A:, $NM#*'-*())7@:, )D$##$N-7=:, +(/$O(*(+7R:1


pri4ate int code1 //-etters and setters %or pri4ate %ields &

ow what we want to do in this page is to print a simple label which displays the status of an order and the date on which the order has been submitted. All the informations about the order will be passed to a
Wicket free user guide

146

1* nternationali<ation with Wicket

String)eso"rceModel with a model containing the bean +rder. The bundle in use contains the following #ey/.alue pairs(
order)tatus.A8Gour pa"ment submitted on W order+ate& has been accepted. order)tatus.@8Gour order submitted on W order+ate& is in progress. order)tatus.=8Gour order submitted on W order+ate& has been shipped. order)tatus.R8Gour order submitted on W order+ate& has been deli4ered.

The .alues abo.e contain a property e,pression ( W order+ate&) that will be e.aluated on the data obHect of the model. The same techniEue can be applied to the resource #ey in order to load the right resource according to the state of the order(
'rder order 8 neC 'rder7neC +ate7:, '*+(*M)T5T0).$NM#*'-*()):1 add7neC /abel79order)tatus9, neC )tring*esource;odel79order)tatus.W status.code&9, ;odel.o%7order::::1

As we can see in the code abo.e also the #ey contains a property e,pression ( W status.code&) which ma#es its .alue dynamic. -n this way the state of an obHect (an 'rder in our e,ample) can determinate which resource will be loaded by String)eso"rceModel. -f we donBt use properties e,pressions we can pro.ide a n"ll .alue as model and in this case String)eso"rceModel will beha.e e,actly as a )eso"rceModel. String)eso"rceModel supports also the same parameter substitution used by standard class 5a!a.te(t.MessageFormat. Parameters can be generic obHects but if we use a model as parameter* String)eso"rceModel will use the data obHect inside it as actual .alue (it will call get+b5ect on the model). Parameters are passed to constructor as a .ararg argument. 9ere is an e,ample of usage of parameter substitution( Ka.a code(
#ropert";odel propert";odel 8 neC #ropert";odel<'rder>7order, 9order+ate9:1 //build a string model Cith tCo parameters: a propert" model and an integer 4alue )tring*esource;odel srm 8 neC )tring*esource;odel79order)tatus.dela"9, null, propert";odel, R:1

Bundle(
order)tatus.dela"8Gour order submitted on W A& has been dela"ed b" @& da"s.

@ne further parameter we can specify when we build a String)eso"rceModel is the component that must be used by the loo#up algorithm. ormally this parameter is not rele.ant* but if we need to use a particular bundle owned by a component not considered by the algorithm* we can specify this component as second parameter. -f we pass all possible parameters to String)eso"rceModelBs constructor we obtain something li#e this(
neC )tring*esource;odel79m"6e"9, m"Component, m";odel, param@, param=, paramR,...:1

12.' 8ummar
-nternationaliCation is a mandatory step if we want to ta#e our applications (and our business;) abroad. !hoosing the right strategy to manage our localiCed resources is fundamental to a.oid to ma#e a mess

Wicket free user guide

147

1* nternationali<ation with Wicket

of them. -n this chapter we ha.e e,plored the built-in support for localiCation pro.ided by 2ic#et* and we ha.e learnt which solutions it offers to manage resource bundles. -n the final part of the chapter we ha.e seen how to localiCe the options displayed by a component (such as :rop:ownChoice or )adioChoice) and we also introduced two new models specifically designed to localiCe our components without introducing in their code any detail about internationaliCation.

Wicket free user guide

148

11 Aesource management with Wicket

1! -esource management with Wicket


@ne of the biggest challenge for a web framewor# is to offer an efficient and consistent mechanism to handle internal resources such as !""/Ka.a"cript files* picture files* pdf and so on. +esources can be static (li#e an icon used across the site) or dynamic (they can be generated on the fly) and they can be made a.ailable to users as a download or as a simple &+:. -n paragraph 3.A we ha.e already seen how to add !"" and Ka.a"cript contents to the header section of the page. -n the first half of this chapter we will learn a more sophisticated techniEue that allows us to manage static resources directly from code and Fpac#G them with our custom components. Then* in the second part of the chapter we will see how to implement custom resources to enrich our web application with more comple, and dynamic functionalities.

13.1 8tatic vs d namic resources


-n 2ic#et a resource is an entity that can interact with the current reEuest and response and -t must implement interface org.apache.wicket.re6"est.reso"rce.2)eso"rce. This interface defines Hust method respond(2)eso"rce.Attrib"tes attrib"tes where the nested class 2)eso"rce. Attrib"tes pro.ides access to reEuest* response and page parameters obHects. +esources can be static or dynamic. "tatic resources donBt entail any computational effort to be generated and they generally correspond to a resource on the filesystem. @n the contrary dynamic resources are generated on the fly when they are reEuested* following a specific logic coded inside them. An e,ample of dynamic resource is the built-in class Captcha2mage)eso"rce in pac#age org. apache.wicket.e(tensions.mark"p.html.captcha which generates a captcha image each time is rendered. As we will see in paragraph 1$.A* de.elopers can build custom resources e,tending base class org.apache.wicket.re6"est.reso"rce.Abstract)eso"rce.

13.2 3esource references


<ost of the times in 2ic#et we wonBt directly instantiate a resource but rather we will use a reference to it. +esource references are represented by abstract class org.apache.wicket.re6"est.reso"rce .)eso"rce)e0erence which returns a concrete resource with factory method get)eso"rce( . -n this way we can laCy-initialiCe resources loading them only the first time they are reEuested.

13.3 Package resources


2ith 9T<: we use to include static resources in our pages using tags li#e <script>* <link> or <img>. This is what we ha.e done so far writing our custom panels and pages. 9owe.er* when we wor# with a component-oriented framewor# li#e 2ic#et* this classic approach becomes inadeEuate because it ma#es custom components hardly reusable. This happens when a component depends on a big number of resources. -n such a case* if somebody wanted to use our custom component in his application* he would be forced to #now which resources it depends on and ma#e them a.ailable. To sol.e this problem 2ic#et allows us to place static resource files into component pac#age (li#e we do with mar#up and properties files) and load them from component code. These #inds of resources are called package resources(
Wicket free user guide

1$%

11 Aesource management with Wicket

llustration 11$1% 7 component with two package resources 4a C'' and a )ava'cript file5$

2ith pac#age resources custom components become independent and self*contained and client code can use them without worrying about their dependencies. To load pac#age resources 2ic#et pro.ides class org.apache.wicket.re6"est.reso"rce. Package)eso"rce)e0erence. To identify a pac#age resource we need to specify a class inside the target pac#age and the name of the desired resource (most of the times this will be a file name). -n the following e,ample ta#en from proHect Image$sPackage"es* C"stomPanel loads a picture file a.ailable as pac#age resource and it displays it in a <img> tag using the built-in component org. apache.wicket.mark"p.html.image.2mage( 9tml(
<html> <head>...</head> <bod"> <Cicket:panel> #ackage resource image: <img Cicket:id89package*es#icture9/> </Cicket:panel> </bod"> </html>

Ka.a code(
public class Custom#anel extends #anel public Custom#anel7)tring id: super7id:1 #ackage*esource*e%erence resource*e%erence 8 neC #ackage*esource*e%erence7getClass7:, 9calendar.2pg9:1 add7neC $mage79package*es#icture9, resource*e%erence::1 & &

2ic#et will ta#e care of generating a .alid &+: for file the following structure(

calendar.2pg.

&+:s for pac#age resources ha.e

<path to application root>/Cicket/resource/<%ull" Euali%ied class name>/<resource %ile name> -<4er-<id>>H.<%ile extension>J

-n our e,ample the &+: for our picture file calendar.2pg is the following(

Wicket free user guide

1$1

11 Aesource management with Wicket

./Cicket/resource/org.CicketTutorial.Custom#anel/calendar-4er-@=S[BB[T<=AAA.2pg

The first part of the &+: is the relati.e path to the application root. -n our e,ample our page is already at the applicationBs root so we ha.e only a single-dotted segment. The ne,t two segments* Cicket and resource* are respecti.ely the namespace and the identifier for resources seen in paragraph 7.A.3. The fourth segment is the fully Eualified name of the class used to locate the resource and it is the scope of the pac#age resource. -n the last segment of the &+: we can find the name of the resource (the file name). As you can see 2ic#et has automatically appended to the file name a .ersion identifier ( 4er@=S[BB[T<=AAA). 2hen 2ic#et runs in DIDI:@P<I T mode this identifier contains the timestamp in millisecond indicating the last time the resource file was modified. This can be useful when we are de.eloping our application and resource files are freEuently modified. Appending the timestamp to the original name we are sure that our browser will use always the last .ersion of the file and not an old* out of date* cached .ersion. 2hen instead 2ic#et is running in DIP:@'<I T mode* the .ersion identifier will contain the <D5 digest of the file instead of the timestamp. The digest is computed only the first time the resource is reEuested. This perfectly ma#es sense as static resources donBt change so often when our application runs into production en.ironment and when this appends the application is redeployed. >ote Pac#age resources can be localiCed following the same rules seen for resource bundles and mar#up files(

llustration 11$*% Package resource locali<ed for (rench language -n the e,ample illustrated in the picture abo.e* if we try to retrie.e pac#age resource calendar.2pg when the current locale is set to =rench* the actual file returned will be calendarM%r.2pg.

13.3.1

0sing package resources with tag <wicket:link>

-n paragraph 7.$ we ha.e used tag <Cicket:link> to automatically create lin#s to boo#mar#able pages. The same techniEue can be used also for pac#age resources in order to use them directly from mar#up file. :etBs assume for e,ample that we ha.e a picture file called icon.png placed in the same pac#age of the current page. &nder these conditions we can display the picture file using the following mar#up fragment(
<Cicket:link> <img src89icon.png9/> </Cicket:link>

-n the e,ample abo.e 2ic#et will populate the attribute


Wicket free user guide

src

with the &+: corresponding to the pac#age 1$4

11 Aesource management with Wicket

resource files.

icon.png. <Cicket:link>

supports also tag

<link>

for !"" files and tag

<script>

for Ka.a"cript

13.# Adding resources to page header section


2ic#et comes with interface org.apache.wicket.mark"p.html.2HeaderContrib"tor which allows components and beha.iors (which will be introduced later in paragraph 15.1) to contribute to the header section of their page. The only method defined in this interface is renderHead (2Header)esponse response where 2Header)esponse is an interface which defines method render(Header2tem item to write static resources or free-form te,t into the header section of the page. 9eader entries are instances of abstract class org.apache.wicket.mark"p.head.Header2tem. 2ic#et pro.ides a set of built-in implementations of this class suited for the most common types of resources. 2ith the e,ception of Priorit,Header2tem* e.ery implementation of Header2tem is an abstract factory class( .ssHeader!tem( represents a !"" resource. =actory methods pro.ided by this class are 0or)e0erence which ta#es in input a resource reference* 0or9rl which creates an !"" item from a gi.en &+: and 0orCSS which ta#es in input an arbitrary !"" string and an optional id .alue to identify the resource. 7ava8criptHeader!tem( represents a Ka.a"cript resource. Kust li#e CssHeader2tem it pro.ides factory methods 0or)e0erence and 0or9rl along with method 0orScript which ta#es in input an arbitrary string representing the script and an optional id .alue to identify the resource. Cn5om3ead Header!tem( it adds Ka.a"cript code that will be e,ecuted after the D@< has been built* but before e,ternal files (such as picture* !""* etc...) ha.e been loaded. The class pro.ides a factory method 0orScript which ta#es in input an arbitrary string representing the script to e,ecute. CnDventHeader!tem( the Ka.a"cript code added with this class is e,ecuted when a specific Ka.a"cript e.ent is triggered on a gi.en D@< element. The factory method is 0orScript(String target4 String e!ent4 CharSe6"ence 5a!aScript * where target is the id of a D@< element (or the element itself)* e!ent is the e.ent that must trigger our code and 5a!aScript is the code to e,ecute. Cn,oadHeader!tem( the Ka.a"cript code added with this class is e,ecuted after the whole page is loaded* e,ternal files included. The factory method is 0orScript(CharSe6"ence 5a!aScript . Priorit Header!tem( it wraps another header item and ensures that it will ha.e the priority o.er the other items during rendering phase. 8tringHeader!tem( with this class we can add an arbitrary te,t to the header section. =actory method is 0orString(CharSe6"ence string . -n the following e,ample our custom component loads a !"" file as a pac#age resource (placed in the same pac#age) and it adds it to header section. Ka.a code(
public class ;"Component extends Component !'4erride public 4oid renderDead7$Deader*esponse response: #ackage*esource*e%erence css3ile 8 neC #ackage*esource*e%erence7this.getClass7:, 9st"le.css9:1

Wicket free user guide

1$$

11 Aesource management with Wicket

CssDeader$tem css$tem 8 CssDeader$tem.%or*e%erence7css3ile:1 response.render7css$tem:1 & &

13.( 3esource dependencies


!lass )eso"rce)e0erence allows to specify the resources it depends on o.erriding method get:ependencies( . The method returns an iterator o.er the set of Header2tems that must be rendered before the resource referenced by )eso"rce)e0erence can be used. This can be really helpful when our resources are Ka.a"cript or !"" libraries that in turn depend on other libraries. =or e,ample we can use this method to ensure that a custom reference to KQuery&- library will find KQuery already loaded in the page(
0rl 2Eue"ui0rl 8 0rl.parse79https://a2ax.googleapis.com/a2ax/libs/2Euer"ui/9 > 9@.@A.=/2Euer"-ui.min.2s9:1 0rl*esource*e%erence 2Euer"ui*e% 8 neC 0rl*esource*e%erence72Eue"ui0rl: !'4erride public $terable<? extends Deader$tem> get+ependencies7: 5pplication application 8 5pplication.get7:1 *esource*e%erence 2Euer"*e% 8 application.getLa4a)cript/ibrar")ettings7:. getLVuer"*e%erence7:1 return 5rra"s.as/ist7La4a)criptDeader$tem.%or*e%erence72Euer"*e%::1 & &1

Please note that in the code abo.e we ha.e built a resource reference using a &+: to the desired library instead of a pac#age resource holding the physical file. The same method get:ependencies( is defined also for class Header2tem.

13.- .ustom resources


-n 2ic#et the best way to add dynamic functionalities to our application (such as cs. e,port* a pdf generated on the fly* etc...) is implementing a custom resource. -n this paragraph as e,ample of custom resource we will build a basic +"" feeds generator which can be used to publish feeds on our site (proHect (ustom"esource4ounting). -nstead of generating a +"" feed by hand we will use +ome 34 framewor# and its utility classes. As hinted abo.e in paragraph 1$.1* class Abstract)eso"rce can be used as base class to implement new resources. This class defines abstract method new)eso"rce)esponse which is in.o#ed when the resource is reEuested. The following is the code of our +"" feeds generator(
public class *))#roducer*esource extends 5bstract*esource !'4erride protected *esource*esponse neC*esource*esponse75ttributes attributes: *esource*esponse resource*esponse 8 neC *esource*esponse7:1 resource*esponse.setContentT"pe79text/xml9:1 resource*esponse.setText(ncoding79ut%-B9:1
42 http: rometools.org

Wicket free user guide

1$3

11 Aesource management with Wicket

resource*esponse.setWriteCallback7neC WriteCallback7: !'4erride public 4oid Crite+ata75ttributes attributes: throCs $'(xception 'utput)tream output)tream 8 attributes.get*esponse7:.get'utput)tream7:1 Writer Criter 8 neC 'utput)treamWriter7output)tream:1 )"nd3eed'utput output 8 neC )"nd3eed'utput7:1 tr" output.output7get3eed7:, Criter:1 & catch 73eed(xception e: throC neC Wicket*untime(xception79#roblems Criting %eed to response...9:1 & & &:1 return resource*esponse1 & // method get3eed7:... &

<ethod new)eso"rce)esponse returns an instance of )eso"rce)esponse representing the response generated by the custom resource. "ince +"" feeds are based on L<:* in the code abo.e we ha.e set the type of the response to text/xml and the te,t encoding to ut%-B. To specify the content that will be returned by our resource we must also pro.ide an implementation of inner class WriteCallback which is responsible for writing content data to responseBs output stream. -n our proHect we used class S,ndFeed+"tp"t from +ome framewor# to write our feed to response. <ethod getFeed( is Hust an utility method that generates a sample +"" feed (which is an instance of interface com.s"n.s,ndication.0eed.s,nd.S,ndFeed). ow that we ha.e our custom resource in place* we can use it in the home page of the proHect. The easiest way to ma#e a resource a.ailable to users is to e,pose it with lin# component )eso"rceLink(
add7neC *esource/ink79rss/ink9, neC *))#roducer*esource7:::1

-n the ne,t paragraphs we will see how to register a resource at application-le.el and how to mount it to an arbitrary &+:.

13.' +ounting resources


Kust li#e pages also resources can be mounted to a specific path. !lass WebApplication pro.ides method mo"nt)eso"rce which is almost identical to mo"ntPage seen in paragraph 7.A.1(
!'4erride public 4oid init7: super.init7:1 //resource mounted to path /%oo/bar *esource*e%erence resource*e%erence 8 neC *esource*e%erence79rss#roducer9: *))*eader*esource rss*esource 8 neC *))*eader*esource7:1 !'4erride public $*esource get*esource7: return rss*esource1

Wicket free user guide

1$5

11 Aesource management with Wicket

&&1 mount*esource79/%oo/bar9, resource*e%erence:1 &

2ith the configuration abo.e (ta#en from proHect (ustom"esource4ounting) e.ery reEuest to will be ser.ed by the custom resource built in the pre.ious paragraph. Parameter placeholders are supported as well(
!'4erride public 4oid init7: super.init7:1 //resource mounted to path /%oo Cith a reEuired indexed parameter *esource*e%erence resource*e%erence 8 neC *esource*e%erence79rss#roducer9: *))*eader*esource rss*esource 8 neC *))*eader*esource7:1 !'4erride public $*esource get*esource7: return rss*esource1 &&1 mount*esource79/bar/W baP&9, resource*e%erence:1 &

/%oo/bar

13.2 8hared resources


+esources can be added to a global registry in order to share them at application-le.el. "hared resources are identified by an application-scoped #ey and they can be easily retrie.ed at a later time using reference class Shared)eso"rce)e0erence. The global registry can be accessed with ApplicationBs method getShared)eso"rces. -n the following e,cerpt of code (ta#en again from proHect (ustom"esource4ounting) we register an instance of our custom +"" feeds producer as application-shared resource(
//init applicationIs method !'4erride public 4oid init7: *))#roducer*esource rss*esource 8 neC *))#roducer*esource7:1 // ... get)hared*esources7:.add79global*))#roducer9, rss*esource:1 &

ow to use an application-shared resource we can simply retrie.e it using class Shared)eso"rce )e0erence and pro.iding the #ey pre.iously used to register the resource(
add7neC *esource/ink79global*ss/ink9, neC )hared*esource*e%erence79global*))#roducer9:::1

The &+: generated for application shared resources follows the same pattern seen for pac#age resources(
./Cicket/resource/org.apache.Cicket.5pplication/global*))#roducer

The last segment of the &+: is the #ey of the resource while the pre.ious segment contains the scope of the resource. =or application-scoped resources the scope is always the fully Eualified name of class Application. This should not be surprising since global resources are .isible at application le.el (i.e.
Wicket free user guide

1$A

11 Aesource management with Wicket

the scope is the application). >ote Pac#age resources are also application-shared resources but they donBt need to be e,plicitly registered. >ote +emember that we can get the &+: of a resource reference using method "rlFor()eso"rce)e0erence reso"rce)e04 PageParameters params a.ailable with both class )e6"estC,cle and class Component.

13.4 .ustomi6ing resource loading.


2ic#et loads applicationBs resources delegating this tas# to a resource locator represented by interface org.apache.wicket.core."til.reso"rce.locator.2)eso"rceStreamLocator. To retrie.e or modify the current resource locator we can use the getter and setter methods defined by setting interface 2)eso"rceSettings(
//init applicationIs method !'4erride public 4oid init7: //get the resource locator get*esource)ettings7:.get*esource)tream/ocator7:1 //set the resource locator get*esource)ettings7:.set*esource)tream/ocator7m"/ocator:1 &

The default locator used by 2ic#et is class )eso"rceStreamLocator which in turn tries to load a reEuested resource using a set of implementations of interface 2)eso"rceFinder. This interface defines method 0ind(Class class4 String pathname which tries to resol.e a resource corresponding to the gi.en class and path. The default implementation of 2)eso"rceFinder used by 2ic#et is ClassPath)eso"rceFinder which searches for resources into the application class path. This is the implementation we ha.e used so far in our e,amples. 9owe.er some de.elopers may prefer storing mar#up files and other resources in a separate folder rather than placing them side by side with Ka.a classes. To customiCe resource loading we can add further resource finders to our application in order to e,tend the resource-loo#up algorithm to different locations. 2ic#et already comes with two other implementations of 2)eso"rceFinder designed to search for resources into a specific folder on the file system. The first is class Path and itBs defined in pac#age org.apache.wicket."til.0ile. The constructor of this class ta#es in input an arbitrary folder that can be e,pressed as a string path or as an instance of 2ic#et utility class Folder (in pac#age org.apache.wicket."til.0ile). The second implementation of interface 2)eso"rceFinder is class WebApplicationPath which loo#s into a folder placed inside webappBs root path (but not inside folder 2IB-- =). ProHect (ustom;olderF4arkup#0ample uses WebApplicationPath to load the mar#up file and the resource bundle for its home page from a custom folder. The folder is called markup3older and it is placed in the root path of the webapp. The following picture illustrates the file structure of the proHect(

Wicket free user guide

1$6

11 Aesource management with Wicket

As we can see in the picture abo.e* we must preser.e the pac#age structure also in the custom folder used as resource container. The code used inside application class to configure WebApplicationPath is the following(
!'4erride public 4oid init7: get*esource)ettings7:.get*esource3inders7:.add7 neC Web5pplication#ath7get)er4letContext7:, 9markup3older9::1 &

<ethod get)eso"rceFinders( defined by setting interface 2)eso"rceSettings returns the list of resource finders defined in our application. The constructor of WebApplicationPath ta#es in input also an instance of standard interface 5a!a(.ser!let.Ser!letConte(t which can be retrie.ed with WebApplicationBs method getSer!letConte(t( . >ote By default* if resource files can not be found inside application classpath* 2ic#et will search for them inside FresourcesG folder. 'ou may ha.e noted this folder in the pre.ious picture. -t is placed ne,t to the folder FHa.aG containing our source files(

Wicket free user guide

1$7

11 Aesource management with Wicket

This folder can be used to store resource files without writing any configuration code.

13.1/ 8ummar
-n this chapter we ha.e learnt how to manage resources with the built-in mechanism pro.ided by 2ic#et. 2ith this mechanism we handle resources from Ka.a code and 2ic#et will automatically ta#e care of generating a .alid &+: for them. 2e ha.e also seen how resources can be bundled as package resources with a component that depends on them to ma#e it self*contained. Then* in the second part of the chapter* we ha.e built a custom resource and we ha.e learnt how to mount it to an arbitrary &+: and how to ma#e it globally a.ailable as shared resource. =inally* in the last part of the paragraph we too# a pee# at the mechanism pro.ided by the framewor# to customiCe the locations where the resource-loo#up algorithm searches for resources.

Wicket free user guide

1$8

13 7n example of integration with )ava'cript

1" 2n example of integration with 3ava4cript


-tBs time to put into practice what we ha.e learnt so far in this guide. To do this we will build a custom date component consisting of a te,t field to edit a date .alue and a fancy calendar icon to open a Ka.a"cript datepic#er. This chapter will also illustrate an e,ample of integration of 2ic#et with a Ka.a"cript library li#e KQuery3$ and its child proHect KQuery &-33.

1#.1 What we want to do...


=or end-users a datepic#er is one of the most appreciated widget. -t allows to simply edit a date .alue with the help of a user-friendly pop-up calendar. ThatBs why nearly all &- framewor#s pro.ide a .ersion of this widget. Popular Ka.a"cript libraries li#e '&- and KQuery come with a ready-to-use datepic#er to enrich the user e,perience of our web applications. 2ic#et already pro.ides a component which integrates a te,t field with a calendar widget from '&- library 35* but there is no built-in component that uses a datepic#er based on KQuery library. As both KQuery and its child proHect KQuery&- ha.e gained a huge popularity in the last years* itBs Euite interesting to see how to integrate them in 2ic#et building a custom component. -n this chapter we will create a custom datepic#er based on the corresponding widget from KQuery&- proHect(

llustration 13$1% How our custom datepicker will look like 4locali<ed for Hnglish5$ Warning @n -nternet you can find different libraries that already offer a strong integration between 2ic#et and KQuery3A. The goal of this chapter is to see how to integrate 2ic#et with a Ka.a"cript framewor# building a simple homemade datepic#er which is not intended to pro.ide e.ery feature of the original Ka.a"cript widget.

1#.1.1
43 44 45 46

What features we want to implement.

http: -5uery.com http: -5ueryui.com 'ee component org$apache$wicket$datetime$markup$html$form$.ateText(ield 'ee #&wicket 4http: code.google.com p -5wicket 5 6 wi&uery 4http: code.google.com p wi5uery 5 or Wicket F )Juery @ 4http: www.Gthweb. net wicketF#&ueryFuiC5

Wicket free user guide

13%

13 7n example of integration with )ava'cript

Before starting to write code* we must clearly define what features we want to implement for our component. The new component should( ;e self?contained( we must be able to distribute it and use it in other proHects without reEuiring any #ind of additional configuration. Have a customi6a=le date format( de.eloper must be able to decide the date format used to display date .alue and to parse user input. ;e locali6a=le( the pop-up calendar must be localiCable in order to support different languages. ThatBs what weBd li#e to ha.e with our custom datepic#er. -n the rest of the chapter we will see how to implement the features listed abo.e and which resources must be pac#aged with our component.

1#.2 ...and how we will do it.


@ur new component will e,tend the a built-in te,t field org.apache.wicket.e(tensions .mark"p.html.0orm.:ate/e(tField which already uses a 5a!a."til.:ate as model obHect and already performs con.ersion and .alidation for input .alues. "ince the component must be selfcontained* we must ensure that the Ka.a"cript libraries it relies on (KQuery and KQuery &-) will be always a.ailable. "tarting from .ersion A.% 2ic#et has adopted KQuery as bac#ing Ka.a"cript library so we can use the .ersion bundled with 2ic#et for our custom datepic#er. To ma#e KQuery &- a.ailable we should instead go to its official site* download the reEuired artifacts and use them as pac#age resources of our component.

1#.2.1

.omponent package resources

KQuery &- needs the following static resources in order to wor# properly( <1uer ?ui.min.<s( the minified .ersion of the library. <1uer ?ui.css( the !"" containing the style used by KQuery &- widgets. <1uer ?ui?i12n.min.<s( the minified Ka.a"cript containing the built-in support for localiCation. Holder AimagesA( the folder containing picture files used by KQuery &- widgets. -n the following picture we can see these pac#age resources with our component class (named .H"er,:ateField)(

Along with the four static resources listed abo.e* we can find also file calendar.Hpg* which is the calendar icon used to open the pop up calendar* and file KQDatePic#er.Hs which contains the following custom Ka.a"cript code that binds our component to a KQuery &- datepic#er(
%unction initLV+atepicker7input$d, countr"$soCode, date3ormat, calendar$con:

Wicket free user guide

131

13 7n example of integration with )ava'cript

4ar localiPed5rra" 8 W.datepicker.regionalHcountr"$soCodeJ1 localiPed5rra"HIbutton$mageIJ 8 calendar$con1 localiPed5rra"HIdate3ormatIJ 8 date3ormat1 initCalendar7localiPed5rra":1 W79X9 > input$d:.datepicker7localiPed5rra":1 &1 %unction initCalendar7localiPed5rra": localiPed5rra"HIchange;onthIJ8 true1 localiPed5rra"HIchangeGearIJ8 true1 localiPed5rra"HIshoC'nIJ 8 IbuttonI1 localiPed5rra"HIbutton$mage'nl"IJ 8 true1 &1

=unction init.H:atepicker ta#es in input the following parameters( input!d( the id of the 9T<: te,t field corresponding to our custom component instance. countr !so.ode( a two-letter low-case -"@ language code. -t can contain also the two-letter upper-case -"@ country code separated with a minus sign (for e,ample en--.) dateHormat( the date format to use for parsing and displaying date .alues. calendar!con( the relati.e &+: of the icon used as calendar icon. As we will see in the ne,t paragraphs* its up to our component to generate this parameters and in.o#e the init.H:atepicker function. =unction initCalendar is a simple utility function that sets the initialiCation array for datepic#er widget. =or more details on KQuery &- datepic#er usage see the documentation at http(//HEueryui.com/ datepic#er.

1#.2.2

!nitiali6ation code

The initialiCation code for our component is contained inside its method on2nitiali3e and is the following(
!'4erride protected 4oid on$nitialiPe7: super.on$nitialiPe7:1 set'utput;arkup$d7true:1 date#attern 8 neC *esource;odel792Euer"+ate3ield.short+ate#attern9, 9mm/dd/""9: .get'b2ect7:1 countr"$soCode 8 neC *esource;odel792Euer"+ate3ield.countr"$soCode9, 9en--.9: .get'b2ect7:1 #ackage*esource*e%erence resource*e%erence 8 neC #ackage*esource*e%erence7getClass7:, 9calendar.2pg9:1 url3or$con 8 url3or7resource*e%erence, neC #age#arameters7::1 dateCon4erter 8 neC #attern+ateCon4erter7date#attern, %alse:1 & !'4erride public <+ate> $Con4erter<+ate> getCon4erter7Class<+ate> t"pe: return 7$Con4erter<+ate>: dateCon4erter1 &

Wicket free user guide

134

13 7n example of integration with )ava'cript

The first thing to do inside on2nitiali3e is to ensure that our component will ha.e a mar#up id for its related te,t field. This is done in.o#ing set+"tp"tMark"p2d(tr"e . e,t* .H"er,:ateField tries to retrie.e the date format and the -"@ language code that must be used as initialiCation parameters. This is done using class )eso"rceModel which searches for a gi.en resource in the a.ailable bundles. -f no .alue is found for date format or for -"@ language code* default .alues will be used (Bmm/dd/""B and Ben--.B). To generate the relati.e &+: for calendar icon* we load it as pac#age resource reference and then we use ComponentBs method "rlFor to get the &+: .alue (we ha.e seen this method in paragraph 6.$.4). The last configuration instruction e,ecuted inside on2nitiali3e is the instantiation of the custom con.erter used by our component. This con.erter is an instance of the built-in class org.apache. wicket.datetime.Pattern:ateCon!ert and must use the pre.iously retrie.ed date format to perform con.ersion operations. ow to tell our component to use this con.erter we must return it o.erriding FormComponentBs method getCon!erter.

1#.2.3

Header contri=utor code

The rest of the code of our custom component is inside method renderHeader* which is responsible for adding to page header the bundled KQuery library* the three files from KQuery &- distribution* the custom file KQDatePic#er.Hs and the in.ocation of function init.H:atepicker(
!'4erride public 4oid renderDead7$Deader*esponse response: super.renderDead7response:1 //i% component is disabled Ce donIt ha4e to load the LVuer"0$ datepicker i%7Fis(nabled$nDierarch"7:: return1 //add bundled LVuer" $La4a)cript/ibrar")ettings 2a4a)cript)ettings 8 get5pplication7:.getLa4a)cript/ibrar")ettings7:1 response.render7La4a)criptDeader$tem.

%or*e%erence72a4a)cript)ettings.getLVuer"*e%erence7:::1
//add package resources response.render7La4a)criptDeader$tem.

%or*e%erence7neC #ackage*esource*e%erence7getClass7:, 92Euer"-ui.min.2s9:::1


response.render7La4a)criptDeader$tem.

%or*e%erence7neC #ackage*esource*e%erence7getClass7:, 92Euer"-ui-i@Bn.min.2s9:::1


response.render7CssDeader$tem.

%or*e%erence7neC #ackage*esource*e%erence7getClass7:, 92Euer"-ui.css9:::1


//add custom %ile LV+ate#icker.2s. *e%erence LV+ate#icker*e% is a static %ield response.render7La4a)criptDeader$tem.%or*e%erence7LV+ate#icker*e%::1 //add the init script %or datepicker )tring 2Euer"+ate3ormat 8 date#attern.replace79""""9, 9""9:.to/oCerCase7:1 )tring init)cript 8 91initLV+atepicker7I9 > get;arkup$d7: > 9I, I9 > countr"$soCode > 9I, I9 > 2Euer"+ate3ormat > 9I, 9 > 9I9 > url3or$con >9I:191 response.render7'n/oadDeader$tem.%or)cript7init)cript::1 &

-f component is disabled the calendar icon must be hidden and no datepic#er must be displayed. ThatBs why renderHeader is s#ipped if component is not enabled. To get a reference to the bundled KQuery library we used the Ka.a"cript setting interface 2.a!a

Wicket free user guide

13$

13 7n example of integration with )ava'cript

ScriptLibrar,Settings and its method get.H"er,)e0erence. -n the last part of renderHeader we build the string to in.o#e function init.H:atepicker using the .alues obtained inside on2nitiali3e. &nfortunately the date format used by KQuery &- is different from the one adopted in Ka.a so we ha.e to con.ert it before building the Ka.a"cript code. This init script is rendered into header section using a +nLoadHeader2tem to ensure that it will be e,ecuted after all the other scripts ha.e been loaded. >ote -f we add more than one instance of our custom component to a single page* static resources are rendered to the header section Hust once. 2ic#et automatically chec#s if a static resource is already referenced by a page and if so* it will not render it again. This does not apply to the init script which is dynamically generated and is rendered for e.ery instance of the component. Warning @ur datepic#er is not ready yet to be used with AKAL. -n chapter 1A we will see how to modify it to ma#e it AKAL-compatible.

1#.3 8ummar
-n this brief chapter we ha.e seen how custom components can be integrated with D9T<: 36 technologies. To do so we ha.e used most of what we ha.e learnt in this guide. ow we are able to build comple, components with a rich user e,perience. 9owe.er this is not enough yet to de.elop 2eb 4.%37 applications. 2e still ha.e to co.er a fundamental technology li#e AKAL and some other 2ic#etrelated topics that will help us building our application in more modular and efficient way.

47 http: en.wikipedia.org wiki @ynamic1H!4% 48 http: en.wikipedia.org wiki .eb1+.,

Wicket free user guide

133

19 Wicket advanced topics

1& Wicket advanced topics


-n this chapter we will learn some ad.anced topics which ha.e not been co.ered yet in the pre.ious chapters but which are nonetheless essential to ma#e the most of 2ic#et and to build sophisticated web applications.

1(.1 Dnriching components with =ehaviors


2ith class org.apache.wicket.beha!ior.1eha!ior 2ic#et pro.ides a .ery fle,ible mechanism to share common features across different components and to enrich e,isting components with further functionalities. As the class name suggests* 1eha!ior adds a generic behavior to a component modifying its mar#up and/or contributing to the header section of the page ( 1eha!ior implements the interface 2HeaderContrib"tor). @ne or more beha.iors can be added to a component with ComponentBs method add(1eha!ior... * while to remo.e a beha.ior we must use method remo!e(1eha!ior . 9ere is a partial list of methods defined inside class 1eha!ior along with a brief description of what they do( =efore3enderJ.omponent component@( called when a component is about to be rendered. after3enderJ.omponent component@( called after a component has been rendered. on.omponent*agJ.omponent componentG .omponent*ag tag@( called when component tag is being rendered. get8tatelessHintJ.omponent component@( returns if a beha.ior is stateless or not. =indJ.omponent component@( called after a beha.ior has been added to a component. un=indJ.omponent component@( called when a beha.ior has been remo.ed from a component. detachJ.omponent component@( o.erriding this method a beha.ior can detach its state before being serialiCed. isDna=ledJ.omponent component@( tells if the current beha.ior is enabled for a gi.en component. 2hen a beha.ior is disabled it will be simply ignored and not e,ecuted. is*emporar J.omponent component@( tells component if the current beha.ior is temporary. A temporary beha.ior is discarded at the end of the current reEuest (i.e itBs e,ecuted only once). on.onfigureJ.omponent component@( called right after the owner component has been configured. on3emoveJ.omponent component@( called when the owner component has been remo.ed from its container. renderHeadJ.omponent componentG !Header3esponse response@ ( o.erriding this method beha.iors can render resources to the header section of the page. =or e,ample the following beha.ior prepends a red asteris# to the tag of a form component if this one is reEuired(
public class *ed5sterisk.eha4ior extends .eha4ior !'4erride public 4oid be%ore*ender7Component component: *esponse response 8 component.get*esponse7:1 )tring.u%%er asterisktDtml 8 neC )tring.u%%er7=AA:1

Wicket free user guide

135

19 Wicket advanced topics

i%7componet instanceo% 3ormComponent UU 773ormComponent:component:.is*eEuired7:: asteriskDtml.append79 <b st"le8\9color:red1%ont-siPe:medium\9>*</b>9:1 & response.Crite7asteriskDtml:1 & &

"ince method be0ore)ender is called before the coupled component is rendered* we can use it to prepend custom mar#up to component tag. This can be done writing our mar#up directly to the current )esponse obHect* as we did in the e,ample abo.e. Please note that we could achie.e the same result o.erriding component method on1e0ore)ender. 9owe.er using a beha.ior we can easily reuse our custom code with any other #ind of component without modifying its source code. As general best practice we should always consider to implement a new functionality using a beha.ior if it can be shared among different #inds of component. Beha.iors play also a strategic role in the built-in AKAL support pro.ided by 2ic#et* as we will see in the ne,t chapter.

1(.2 Generating call=ack 03,s with !3e1uest,istener


2ith 2ic#et itBs Euite easy to build a callback :"% that e,ecutes a specific method on ser.er side. This method must be defined in a functional interfaceFE that inherits from built-in org.apache.wicket. 2)e6"estListener and it must be a .oid method with no parameters in input(
public inter%ace $;"/istener extends $*eEuest/istener /** * Called Chen the relati4e callback 0*/ is reEuested. */ 4oid m"Callback;ethod7:1 &

To control how the method will be in.o#ed we must use class org.apache.wicket.)e6"est Listener2nter0ace. -n 2ic#et is a common practice to instantiate this class as a public static field inside the relati.e callbac# interface(
public inter%ace $;"/istener extends $*eEuest/istener /***eEuest/istener$nter%ace instance*/ public static %inal *eEuest/istener$nter%ace $NT(*35C( 8 neC *eEuest/istener$nter%ace7$;"/istener.class:1 /** * Called Chen the relati4e callback 0*/ is reEuested. */ 4oid m"Callback;ethod7:1 &

By default )e6"estListener2nter0ace will respond rendering the current page after the callbac# method has been e,ecuted (if we ha.e a non-AKAL reEuest). To change this beha.ior we can use setter
49 7 functional interface is an an interface that defines #ust one method$

Wicket free user guide

13A

19 Wicket advanced topics

method set)enderPageA0ter2n!ocation(boolean . ow that our callbac# interface is complete we can generate a callbac# &+: with ComponentBs method "rlFor()e6"estListener2nter0ace4 PageParameters or with method "rlFor (1eha!ior4 )e6"estListener2nter0ace4 PageParameters if we are using a callbac# interface with a beha.ior (see the following e,ample). ProHect (allback:"%#0ample contains a beha.ior (class +nChangeSingleChoice1eha!ior) that implements a callbac# interface to update the model of an AbstractSingleSelectChoice component when user changes the selected option (it pro.ides the same functionality of method want +nSelectionChangedNoti0ications). -nstead of a custom callbac# interface* +nChangeSingleChoice1eha!ior implements built-in interface org.apache.wicket.beha!ior.21eha!iorListener which is designed to generate a callbac# &+: for beha.iors. The callbac# method defined in this interface is on)e6"est( and the following is the implementation pro.ided by +nSelectionChangedNoti0ications(
!'4erride public 4oid on*eEuest7: *eEuest reEuest 8 *eEuestC"cle.get7:.get*eEuest7:1 $*eEuest#arameters reEuest#arameters 8 reEuest.get*eEuest#arameters7:1 )tringOalue choice$d 8 reEuest#arameters.get#arameterOalue79choice$d9:1 //boundComponent is the component that the beha4ior it is bound to. boundComponent.set+e%ault;odel'b2ect7con4ertChoice$dToChoice7choice$d.to)tring7:::1 &

2hen in.o#ed .ia &+:* the beha.ior e,pects to find a reEuest parameter ( choice$d) containing the id of the selected choice. This .alue is used to obtain the corresponding choice obHect that must be used to set the model of the component that the beha.ior is bound to ( boundComponent). <ethod con!ertChoice2d/oChoice is in charge of retrie.ing the choice obHect gi.en its id and it has been copied from class AbstractSingleSelectChoice. Another interesting part of +nChangeSingleChoice1eha!ior is its method onComponent/ag where some Ka.a"cript FmagicG is used to mo.e userBs browser to the callbac# &+: when e.ent FchangeG occurs on bound component(
!'4erride public 4oid onComponentTag7Component component, ComponentTag tag: super.onComponentTag7component, tag:1 Char)eEuence call.ack0*/ 8 getCallback0rl7:1 )tring separatorChar 8 7call.ack0*/.to)tring7:.index'%7I?I: > -@ ? 9U9 : 9?9:1 )tring %inal)cript 8 94ar is)elect 8 W7this:.is7IselectI:1\n9 > 94ar component1\n9 > 9i%7is)elect:\n9 > 9 9 component 8 W7this:1\n9 > component 8 W7this:.%ind7Iinput:radio:checkedI:1\n9 > separatorChar > 9else \n9 > 9CindoC.location.hre%8I9 > call.ack0*/ > 9choice$d8I > 9 > 9component.4al7:91 tag.put79onchange9, %inal)cript:1 &

The goal of onComponent/ag is to build an


Wicket free user guide

onchange

handler that forces userBs browser to mo.e to 136

19 Wicket advanced topics

the callbac# &+: (modifing standard property CindoC.location.hre%). Please note that we ha.e appended the e,pected parameter (choice$d) to the &+: retrie.ing its .alue with a KQuery selector suited for the current type of component (a drop-down menu or a radio group). "ince we are using KQuery in our Ka.a"cript code* the beha.ior comes also with method renderHead that adds the bundled KQuery library to the current page. <ethod getCallback9rl( is used to generate the callbac# &+: for our custom beha.ior and it has been copied from built-in class AbstractA5a(1eha!ior(
public Char)eEuence getCallback0rl7: i% 7boundComponent 88 null: throC neC $llegal5rgument(xception7 9.eha4ior must be bound to a component to create the 0*/9:1 & %inal *eEuest/istener$nter%ace rli1 rli 8 $.eha4ior/istener.$NT(*35C(1 return boundComponent.url3or7this, rli, neC #age#arameters7::1 &

"tatic field 21eha!iorListener.2N/')FAC' is the implementation of )e6"estListener 2nter0ace defined inside callbac# interface 21eha!iorListener. The home page of proHect (allback:"%#0ample contains a :rop:ownChoice and a )adioChoice which use our custom beha.ior. There are also two labels to display the content of the models of the two components(

>ote -mplementing interface 21eha!iorListener ma#es a beha.ior stateful because its callbac# &+: is specific for a gi.en instance of component.

1(.3 Wicket events infrastructure


"tarting from .ersion 1.5 2ic#et offers an e.ent-based infrastructure for inter-component communication. The infrastructure is based on two simple interfaces (both in pac#age org. apache.wicket.e!ent) ( 2'!entSo"rce and 2'!entSink. The first interface must be implemented by those entities that want to broadcast en e.ent while the second interface must be implemented by those entities that want to recei.e a broadcast e.ent. The following entities already implement both these two interfaces (i.e. they can be either sender or recei.er)( Component4 Session4 )e6"estC,cle and Application. 2'!entSo"rce e,poses a single method named send which ta#es in input three parameters( sink( an implementation of 2'!entSink that will be the recei.er of the e.ent. =roadcast( a 1roadcast enum which defines the broadcast method used to dispatch the e.ent to the sin# and to other entities such as sin# children* sin# containers* session obHect*
Wicket free user guide

137

19 Wicket advanced topics

application obHect and the current reEuest cycle. -t has four possible .alues( Ealue B+IADT9 DIPT9 5escription The e.ent is sent first to the specified sin# and then to all its children components following a breadth-first order. The e.ent is sent to the specified sin# only after it has been dispatched to all its children components following a depth-first order. The e.ent is sent first to the specified sin# and then to its parent containers. The e.ent is sent only to the specified sin#.

B&BB:I ILA!T

pa load( a generic obHect representing the data sent with the e.ent.

Iach broadcast mode has its own tra.ersal order for Session4 )e6"estC,cle and Application. "ee Ka.aDoc of class 1roadcast for further details about this order. -nterface 2'!entSink e,poses callbac# method on'!ent(2'!ent7D8 e!ent which is triggered when a sin# recei.es an e.ent. The interface 2'!ent represents the recei.ed e.ent and pro.ides getter methods to retrie.e the e.ent broadcast type* the source of the e.ent and its payload. Typically the recei.ed e.ent is used chec#ing the type of its payload obHect (
!'4erride public 4oid on(4ent7$(4ent e4ent: //i% the t"pe o% pa"load is ;"#a"loadClass per%orm some actions i%7e4ent.get#a"load7: instanceo% ;"#a"loadClass: //execute some business code. &else //other business code & &

ProHect Inter(omponets#vents#0ample pro.ides a concrete e,ample of sending an e.ent to a component (named Bcontainer in the middleB) using all the a.ailable broadcast methods(

llustration 19$1% Pro#ect nterComponentsHventsHxample displaying the order in which the entities are notified using broadcast type B@BB0H

Wicket free user guide

138

19 Wicket advanced topics

1(.# !nitiali6ers
"ome components or resources may need to be configured before being used in our applications. 2hile so far we used ApplicationBs init method to initialiCe these #inds of entities* 2ic#et offers a more fle,ible and modular way to configure our classes. During applicationBs bootstrap 2ic#et searches for any properties file named wicket.properties placed in one of the classpath roots .isible to the application 5%. 2hen one of these files is found* the initiali<er defined inside it will be e,ecuted. An initialiCer is an implementation of interface org.apache.wicket.22nitiali3er and is defined inside wicket.properties with a line li#e this(
initialiPer8org.CicketTutorial.;"$nitialiPer

The fully Eualified class name corresponds to the initialiCer that must be e,ecuted. -nterface 22nitiali3er defines method init(Application which should contain our initialiCation code* and method destro,(Application which is in.o#ed when application is terminated(
public class ;"$nitialiPer implements $$nitialiPer public 4oid init75pplication application: //initialiPation code & public 4oid destro"75pplication application: //code to execute Chen application is terminated & &

@nly one initialiCer can be defined in a single wicket.properties file. To o.ercome this limit we can create a main initialiCer that in turn e,ecutes e.ery initialiCer we need(
public class ;ain$nitialiPer implements $$nitialiPer public 4oid init75pplication application: neC 5nother$nitialiPer7:.init7application:1 neC Get5nother$nitialiPer7:.init7application:1 //... & //destro"... &

1(.( 0sing 7+9 with Wicket


K<L (3ava 4anagement #0tensions) is the standard technology adopted in Ka.a for managing and monitoring running applications or Ka.a Dirtual <achines. 2ic#et offers support for K<L through module Cicket-2mx. -n this paragraph we will see how we can connect to a 2ic#et application using K<L. -n our e,ample we will use K!onsole as K<L client. This program is bundled with Ka.a "I since .ersion 5 and we can run it typing 2console in our @" shell. @nce K!onsole has started it will as# us to establish a new connection to a Ka.a process* choosing between a local process or a remote one. -n the following picture we ha.e selected the process corresponding to the local instance of Ketty ser.er we used to run one of our e,ample proHects(

50

This set of classpath roots includes the root of the package of the application class and the roots of the visible )7As

Wicket free user guide

15%

19 Wicket advanced topics

After we ha.e established a K<L connection* K!onsole will show us the following set of tabs

K<L e,poses application-specific informations using special obHects called <Beans ( 4anageable 9eans)* hence if we want to control our application we must open the corresponding tab. The <Beans containing the applicationBs informations is named org.apache.Cicket.app.<%ilter/ser4let name>. -n our e,ample we ha.e used Cicket.test as filter name51 for our application(

51 We have discussed filter name and web$xml in paragraph *$*$1$

Wicket free user guide

151

19 Wicket advanced topics

As we can see in the picture abo.e* e.ery <Bean e,poses a node containing its attributes and another node showing the possible operations that can be performed on the obHect. -n the case of a 2ic#et application the a.ailable operations are clearMark"pCache and clearLocali3erCache(

2ith these two operations we can force 2ic#et to clear the internal caches used to load components mar#up and resource bundles. This can be particularly useful if we ha.e our application running in DIP:@'<I T mode and we want to publish minor fi,es for mar#up or bundle files (li#e spelling or typo corrections) without restarting the entire application. 2ithout cleaning these two caches 2ic#et would continue to use cached .alues ignoring any change made to mar#up or bundle files. "ome of the e,posed properties are editable* hence we can tune their .alues while the application is running. =or e,ample if we loo# at the properties of ApplicationSettings we can set the ma,imum siCe allowed for an upload modifying the attribute :e0a"ltMa(im"m9ploadSi3e(

1(.- Generating H*+, markup from code.


"o far* as mar#up source for our pages/panels we ha.e used a static mar#up file* no matter if it was inherited or directly associated to the component. ow we want to in.estigate a more comple, use case where we want to dynamical generate the mar#up directly inside component code. To become a mar#up producer* a component must simply implement interface org.apache. wicket.mark"p.2Mark"p)eso"rceStreamPro!ider. The only method defined in this interface is getMark"p)eso"rceStream(Mark"pContainer4 Class7D8 which returns an utility interface called 2)eso"rceStream representing the actual mar#up. -n the following e,ample we ha.e a custom panel without a related mar#up file that generates a simple
Wicket free user guide

154

19 Wicket advanced topics

<di4> tag

as mar#up(

public class 5uto;arkup-en#anel extends #anel implements $;arkup*esource)tream#ro4ider public 5uto;arkup-en#anel7)tring id, $;odel<?> model: super7id, model:1 & !'4erride public $*esource)tream get;arkup*esource)tream7;arkupContainer container, Class<?> containerClass: )tring markup 8 9<di4>#anel markup</di4>91 )tring*esource)tream resource)tream 8 neC )tring*esource)tream7markup:1 return resource)tream1 & &

!lass String)eso"rceStream is a resource stream that uses a String instance as bac#ing obHect.

1(.-.1

Avoiding markup caching

As we ha.e seen in the pre.ious paragraph* 2ic#et uses an internal cache for components mar#up. This can be a problem if our component dynamical generates its mar#up when it is rendered because once the mar#up has been cached* 2ic#et will always use the cached .ersion for the specific component. To o.erwrite this default caching policy* a component can implement interface 2Mark"pCache;e,Pro!ider. This interface defines method getCache;e,(Mark"pContainer4 Class7D8 which returns a string .alue representing the #ey used by 2ic#et to retrie.e the mar#up of the component from the cache. -f this .alue is n"ll the mar#up will not be cached* allowing the component to display the last generated mar#up each time it is rendered(
public class NoCache;arkup#anel extends #anel implements $;arkupCache6e"#ro4ider public NoCache;arkup#anel7)tring id, $;odel<?> model: super7id, model:1 & /** * -enerate a d"namic DT;/ markup that changes e4er" time * the component is rendered */ !'4erride public $*esource)tream get;arkup*esource)tream7;arkupContainer container, Class<?> containerClass: )tring markup 8 9<di4>#anel Cith current nanotime: 9 > )"stem.nanoTime7: > 9</di4>91 )tring*esource)tream resource)tream 8 neC )tring*esource)tream7markup:1 return resource)tream1 & /** * 54oid markup caching %or this component */

Wicket free user guide

15$

19 Wicket advanced topics

!'4erride public )tring getCache6e"7;arkupContainer argA, Class<?> arg@: return null1 & &

1(.' 8ummar
-n this chapter we ha.e introduced some ad.anced topics we didnBt ha.e the chance to co.er yet. 2e ha.e started tal#ing about beha.iors and we ha.e seen how they can be used to enrich e,isting components (promoting a component-oriented approach). Beha.iors are also fundamental to wor# with AKAL in 2ic#et* as we will see in the ne,t chapter. After beha.iors we ha.e learnt how to generate callbac# &+:s to e,ecute a custom method on ser.er side defined inside a specific callbac# interface. The third topic of the chapter has been the e.ent infrastructure pro.ided in 2ic#et for inter-component communication which brings to our components a des#top-li#e e.ent-dri.en architecture. Then* we ha.e introduced a new entity called initialiCer which can be used to configure resources and component in a modular and self-contained way. 2e ha.e also loo#ed at 2ic#et support for K<L and we ha.e seen how to use this technology for monitoring and managing our running applications. =inally we ha.e introduced a new techniEue to generate the mar#up of a component from its Ka.a code.

Wicket free user guide

153

18 Working with 7)7?

1( Working with 2325


AKAL has become a must*have for nearly all #inds of web application. This technology does not only help to achie.e a better user e,perience but it also allows to impro.e the bandwidth performance of web applications. &sing AKAL usually means writing tons of Ka.a"cript code to handle asynchronous reEuests and to update user interface* but with 2ic#et we can lea.e all this boilerplate code to the framewor# and we donBt e.en need to write a single line of Ka.a"cript to start using AKAL. -n this chapter we will learn how to le.erage the AKAL support pro.ided by 2ic#et to ma#e our applications fully web +.,54 compliant.

1-.1 How to use A7A9 components and =ehaviors.


2ic#et support for AKAL is implemented in file Cicket-a2ax-2Euer".2s which ma#es complete transparent to Ka.a code any detail about AKAL communication. AKAL components and beha.iors shipped with 2ic#et e,pose one or more callbac# methods which are e,ecuted when they recei.e an AKAL reEuest. @ne of the arguments of these methods is an instance of interface org.apache.wicket.a5a(.A5a()e6"est/arget. =or e,ample component A5a(Link (in pac#age org.apache.wicket.a5a(.mark"p.html) defines abstract method onClick(A5a()e6"est/arget target which is e,ecuted when user clic#s on the component(
neC 52ax/ink79a2ax/ink9: !'4erride public 4oid onClick752ax*eEuestTarget target: //some ser4er side code... & &1

&sing A5a()e6"est/arget we can specify the content that must be sent bac# to the client as response to the current AKAL reEuest. The most commonly used method of this interface is probably add(Component... components . 2ith this method we tell 2ic#et to render again the specified components and refresh their mar#up .ia AKAL(
neC 52ax/ink79a2ax/ink9: !'4erride public 4oid onClick752ax*eEuestTarget target: //modi%" the model o% a label and re%resh it on broCser label.set+e%ault;odel'b2ect795nother 4alue < label.9:1 target.add7label:1 & &1

!omponents can be refreshed .ia AHa, only if they ha.e rendered a mar#up id for their related tag. As a conseEuence* we must remember to set a .alid id .alue on e.ery component we want to add to A5a()e6"est/arget. This can be done using one of the two methods seen in paragraph 3.$(

52 http: en.wikipedia.org wiki .eb1+.,

Wicket free user guide

155

18 Working with 7)7?

%inal /abel label 8 neC /abel79labelComponent9, 9$nitial 4alue.9:1 //autogenerate a markup id label.set'utput;arkup$d7 true:1 add7label:1 //... neC 52ax/ink79a2ax/ink9: !'4erride public 4oid onClick752ax*eEuestTarget target: //modi%" the model o% a label and re%resh it on client side label.set+e%ault;odel'b2ect795nother 4alue < label.9:1 target.add7label:1 & &1

Another common use of A5a()e6"est/arget is to prepend or append some Ka.a"cript code to the generated response. =or e,ample the following AKAL lin# displays an alert bo, as response to userBs clic#(
neC 52ax/ink79a2ax/ink9: !'4erride public 4oid onClick752ax*eEuestTarget target: target.appendLa4a)cript791alert7IDelloFFI:19:1 & &1

Warning +epeaters component that ha.e org.apache.wicket.mark"p.repeater Abstract)epeater as base class (li#e List-iew* )epeating-iew* etc...) can not be directly updated .ia AKAL. if we want to refresh their mar#up .ia AKAL we must add one of their parent containers to the A5a()e6"est/arget.

1-.2 ;uilt?in A7A9 components


2ic#et distribution comes with a number of built-in AKAL components ready to be used. "ome of them are the a-a0ified .ersion of common components li#e lin#s and buttons* while others are AKAL-specific components. AKAL components are not different from any other component seen so far and they donBt reEuire any additional configuration to be used. As we will shortly see* switching from a classic lin# or button to the aHa,ified .ersion is Hust a matter of appending FAHa,G to the component class name. This paragraph pro.ides an o.er.iew of what we can find in 2ic#et to start writing AKAL-enhanced web applications.

1-.2.1

,inks and =uttons

-n the pre.ious paragraph we ha.e already introduced component A5a(Link. 2ic#et pro.ides also the aHa,ified .ersions of submitting components S"bmitLink and 1"tton which are simply called A5a(S"bmitLink and A5a(1"tton. These components come with a .ersion of methods onS"bmit* on'rror and onA0terS"bmit that ta#es in input also an instance of A5a()e6"est/arget. Both components are in pac#age org.apache.wicket.a5a(.mark"p.html.0orm.

1-.2.2

Hall=ack components
15A

Wicket free user guide

18 Working with 7)7?

Building an entire site using AKAL can be ris#y as some clients may not support this technology. -n order to pro.ide an usable .ersion of our site also to these clients* we can use components A5a(FallbackLink and A5a(Fallback1"tton which are able to automatically degrade to a standard lin# or to a standard button if client doesnBt support AKAL.

1-.2.3

A7A9 .heck=ox

!lass org.apache.wicket.a5a(.mark"p.html.0orm.A5a(Check1o( is a chec#bo, component that updates its model .ia AKAL when user changes its .alue. -ts AKAL callbac# method is on9pdate(A5a()e6"est/arget target . The component e,tends standard chec#bo, component Check1o( adding an A5a(FormComponent9pdating1eha!ior to itself (we will see this beha.ior later in paragraph 1A.$.$).

1-.2.#

A7A9 edita=le la=els

An editable label is a special label that can be edited by the user when she/he clic#s on it. 2ic#et ships three different implementations for this component (all inside pac#age org.apache.wicket. e(tensions.a5a(.mark"p.html)( A<axDdita=le,a=el( itBs a basic .ersion of editable label. &ser can edit the content of the label with a te,t field. This is also the base class for the other two editable labels. A<axDdita=le+ulti,ine,a=el( this label supports multi-line .alues and uses a te,t area as editor component. A<axDdita=le.hoice,a=el( this label uses a drop-down menu to edit its .alue. Base component A5a('ditableLabel e,poses the following set of AKAL-aware methods that can be o.erriden( onDditJA<ax3e1uest*arget target@( called when user clic#s on component. The default implementation shows the component used to edit the .alue of the label. on8u=mitJA<ax3e1uest*arget target@( called when the .alue has been successfully updated with the new input. onDrrorJA<ax3e1uest*arget target@( called when the new inserted input has failed .alidation. on.ancelJA<ax3e1uest*arget target@( called when user has e,ited from editing mode pressing escape #ey. The default implementation brings bac# the label to its initial state hiding the editor component. 2ic#et module wicket@e(amples contains page class 'ditableLabelPage.5a!a which shows all these three components together. 'ou can see this page in action at http(//www.wic#etlibrary.com/wic#et-e,amples-A.%.,/aHa,/editable-label(

llustration 18$1% The edit label example bundled with Wicket

Wicket free user guide

156

18 Working with 7)7?

1-.2.(

Autocomplete text field

@n -nternet we can find many e,amples of te,t fields that display a list of suggestions (or options) while the user types a te,t inside them. This feature is #nown as autocomplete functionality. 2ic#et offers an out-of-the-bo, implementation of an autocomplete te,t field with component org.apache.wicket.e(tensions.a5a(.mark"p.html.a"tocomplete.A"toComplete/e(tFi eld. 2hen using A"toComplete/e(tField we are reEuired to implement its abstract method getChoices(String inp"t where the inp"t parameter is the current input of the component. This method returns an iterator o.er the suggestions that will be displayed as a drop-down menu(

llustration 18$*% The autocomplete example bundled with Wicket "uggestions are rendered using a render which implements interface 2A"toComplete)enderer. The default implementation simply calls toString( on each suggestion obHect. -f we need to wor# with a custom render we can specify it .ia component constructor. A"toComplete/e(tField supports a wide range of settings that are passed to its constructor with class A"toCompleteSettings. @ne of the most interesting parameter we can specify for A"toComplete/e(tField is the throttle delay which is the amount of time (in milliseconds) that must elapse between a change of input .alue and the transmission of a new AHa, reEuest to display suggestions. This parameter can be set with method set/hrottle:ela,(int (
5utoComplete)ettings settings 8 neC 5utoComplete)ettings7:1 //set throttle to <AA ms: component Cill Cait <AAms be%ore displa"ing the options settings.setThrottle+ela"7<AA:1 //... 5utoCompleteText3ield %ield 8 neC 5utoCompleteText3ield<T>79%ield9, model: !'4erride protected $terator getChoices7)tring argA: //return an iterator o4er the options & &1

2ic#et module wicket@e(amples contains page class A"toCompletePagePage.5a!a which shows an e,ample of autocomplete te,t field. The running e,ample is a.ailable at http(//www.wic#etlibrary.com/wic#et-e,amples-A.%.,/aHa,/autocomplete.

1-.2.-

+odal window

!lass org.apache.wicket.e(tensions.a5a(.mark"p.html.modal.ModalWindow is an impWicket free user guide

157

18 Working with 7)7?

lementation of a modal window5$ based on AKAL(

llustration 18$1% The modal window from pro#ect Basic/odalWindowHxample The content of a modal window can be either another component or a page. -n the first case the id of the component used as content must be retrie.ed with method getContent2d( . -f instead we want to use a page as window content* we must implement the inner interface ModalWindow.Page(reator and pass it to method setPageCreator. The page used as content will be embedded in a <i%rame> tag. To display a modal window we must call its method show(A5a()e6"est/arget target . This is usually done inside the AKAL callbac# method of another component (li#e an A5a(Link). The following mar#up and code are ta#en from proHect 9asic4odal.indow#0ample and illustrate a basic usage of a modal window( 9tml(
<bod"> <h=>;odal Windod example</h=> <a Cicket:id89openWindoC9>'pen the CindoCF</a> <di4 Cicket:id89modalWindoC9></di4> </bod">

Ka.a code(
public Dome#age7%inal #age#arameters parameters: super7parameters:1 %inal ;odalWindoC modalWindoC 8 neC ;odalWindoC79modalWindoC9:1 /abel label 8 neC /abel7modalWindoC.getContent$d7:, 9$Im a modal CindoCF9:1 modalWindoC.setContent7label:1 modalWindoC.setTitle79;odal CindoC9:1 add7modalWindoC:1 add7neC 52ax/ink79openWindoC9: !'4erride public 4oid onClick752ax*eEuestTarget target: modalWindoC.shoC7target:1 &
53 http: en.wikipedia.org wiki 4odal1window

Wicket free user guide

158

18 Working with 7)7?

&:1 &

Kust li#e any other component also ModalWindow must be added to a mar#up tag* li#e we did in our e,ample using a <di4> tag. 2ic#et will automatically hide this tag in the final mar#up appending the style .alue displa":none. The component pro.ides different setter methods to customiCe the appearance of the window( set*itleJ8tring@( specifies the title of the window set3esi6a=leJ=oolean@( by default the window is resiCeable. -f we need to ma#e its siCe fi,ed we can use this method to turn off this feature. set!nitialWidthJint@ and set!nitialHeightJint@( set the initial dimensions of the window. set+inimalWidthJint@ and set+inimalHeightJint@( specify the minimal dimensions of the window. set.ookie>ameJ8tring@( this method can be used to specify the name of the coo#ie used on client side to store siCe and position of the window when it is closed. The component will use this coo#ie to restore these two parameters the ne,t time the window will be opened. -f no coo#ie name is pro.ided* the component will not remember its last position and siCe. set.ss.lass>ameJ8tring@( specifies the !"" class used for the window. setAuto8i6eJ=oolean@( when this flag is set to tr"e the window will automatically adHust its siCe to fit content width and height. By default it is 0alse. The modal window can be closed from code using its method close(A5a()e6"est/arget target . The currently opened window can be closed also with the following Ka.a"cript instruction(
Wicket.WindoC.get7:.close7:1

ModalWindow gi.es the opportunity to perform custom actions when window is closing. -nner interface ModalWindow..indow(losed(allback can be implemented and passed to windowBs method setWindowClosedCallback to specify the callbac# that must be e,ecuted after window has been closed(
modalWindoC.setWindoCClosedCallback7neC ;odalWindoC.WindoCClosedCallback7: !'4erride public 4oid onClose752ax*eEuestTarget target: //custom code... & &:1

1-.2.'

*ree repeaters

!lass org.apache.wicket.e(tensions.mark"p.html.repeater.tree.Abstract/ree is the base class of another family of repeaters called tree repeaters and designed to display a data hierarchy as a tree* resembling the beha.ior and the loo# Y feel of des#top tree components. A classic e,ample of tree component on des#top is the tree used by nearly all file managers to na.igate file system(

Wicket free user guide

1A%

18 Working with 7)7?

llustration 18$3% (ile system tree on Windows ?P 4on the left5 and @buntu 4on the right5 Because of their highly interacti.e nature* tree repeaters are implemented as AKAL components* meaning that they are updated .ia AKAL when we e,pand or collapse their nodes. The basic implementation of a tree repeater shipped with 2ic#et is component Nested/ree. -n order to use a tree repeater we must pro.ide an implementation of interface 2/reePro!ider which is in charge of returning the nodes that compose the tree. 2ic#et comes with a built-in implementation of 2/reePro!ider called /reeModelPro!ider that wor#s with the same tree model 53 and nodes used by "wing component 5a!a(.swing../ree. These "wing entities should be familiar to you if you ha.e pre.iously wor#ed with the old tree repeaters (components /ree and /ree/able) that ha.e been deprecated with 2ic#et A and that are strongly dependent on "wing-based model and nodes. /reeModelPro!ider can be used to migrate your code to the new tree repeaters. -n the ne,t e,ample (proHect (heck9o0$-a0!ree) we will build a tree that displays some of the main cities of three Iuropean countries( -taly* 0ermany and =rance. The cities are sub-nodes of a main node representing the relati.e county. The nodes of the final tree will be also selectable with a chec#bo, control. The whole tree will ha.e the classic loo# Y feel of 2indows LP. This is how our tree will loo# li#e(

llustration 18$9% The tree repeater from pro#ect CheckBox7#axTree 2e will start to e,plore the code of this e,ample from the home page. The first portion of code we will see is where we build the nodes and the /reeModelPro!ider for the three. As tree node we will use "wing class 5a!a(.swing.tree.:e0a"ltM"table/reeNode(
public class Dome#age extends Web#age public Dome#age7%inal #age#arameters parameters:
54 Tree model is an implementation of interface #avax$swing$tree$Tree/odel and it has nothing to do with Wicket models,

Wicket free user guide

1A1

18 Working with 7)7?

super7parameters:1 +e%ault;utableTreeNode root 8 neC +e%ault;utableTreeNode79Cities o% (urope9:1

addNodes7addNodes7root, 9$tal"9:, 9*ome9, 9Oenice9, 9;ilan9, 93lorence9:1 addNodes7addNodes7root, 9-erman"9:,9)tuttgart9,9;unich9,9.erlin9,9+usseldor%9, 9+resden9:1 addNodes7addNodes7root, 93rance9:, 9#aris9,9Toulouse9,9)trasbourg9,9.ordeaux9, 9/"on9:1
+e%aultTree;odel tree;odel 8 neC +e%aultTree;odel7root:1 Tree;odel#ro4ider<+e%ault;utableTreeNode> model#ro4ider 8 neC Tree;odel#ro4ider<+e%ault;utableTreeNode>7tree;odel: !'4erride public $;odel<+e%ault;utableTreeNode> model7+e%ault;utableTreeNode ob2ect: return ;odel.o%7ob2ect:1 & &1 //To be continued...

odes ha.e been built using simple strings as data obHects and in.o#ing custom utility method addNodes which con.erts string parameters into children nodes for a gi.en parent node. @nce we ha.e our tree of :e0a"ltM"table/reeNodes we can build the "wing tree model ( :e0a"lt/reeModel) that will be the bac#ing obHect for a /reeModelPro!ider. This pro.ider wraps each node in a model in.o#ing its abstract method model. -n our e,ample we ha.e used a simple Model as wrapper model. "crolling down the code we can see how the tree component is instantiated and configured before being added to the home page(
//Continued %rom pre4ious snippet... NestedTree<+e%ault;utableTreeNode> tree 8 neC NestedTree<+e%ault;utableTreeNode>79tree9, model#ro4ider:

!'4erride protected Component neCContentComponent7)tring id, $;odel<+e%ault;utableTreeNode>model: return neC Checked3older<+e%ault;utableTreeNode>7id, this, model:1 & &1 //select WindoCs theme tree.add7neC WindoCsTheme7::1 add7tree:1 & //implementation o% addNodes //... &

To use tree repeaters we must implement their abstract method newContentComponent which is called internally by base class Abstract/ree when a new node must be built. As content component we ha.e used built-in class CheckedFolder which combines a Folder component with a Check1o( form control. The final step before adding the tree to its page is to apply a theme to it. 2ic#et comes with two beha.iors* Windows/heme and H"man/heme* which correspond to the classic 2indows LP theme and to the 9uman theme from &buntu.

Wicket free user guide

1A4

18 Working with 7)7?

@ur chec#able tree is finished but our wor# is not o.er yet because the component doesnBt offer many functionalities as it is. &nfortunately neither Nested/ree nor CheckedFolder pro.ide a means for collecting chec#ed nodes and returning them to client code. -tBs up to us to implement a way to #eep trac# of chec#ed nodes. Another nice feature we would li#e to implement for our tree is the following user-friendly beha.ior that should occur when a user chec#s/unchec#s a node( 2hen a node is chec#ed also all its children nodes (if any) must be chec#ed. 2e must also ensure that all the ancestors of the chec#ed node (root included) are chec#ed* otherwise we would get an inconsistent selection. 2hen a node is unchec#ed also all its children nodes (if any) must be unchec#ed and we must also ensure that ancestors get unchec#ed if they ha.e no more chec#ed children. The first goal (#eeping trac# of chec#ed node) can be accomplished building a custom .ersion of CheckedFolder that uses a shared Ka.a Set to store chec#ed node and to .erify if its node has been chec#ed. This #ind of solution reEuires a custom model for chec#bo, component in order to reflect its chec#ed status when its container node is rendered. This model must implement typed interface 2Model71oolean8 and must be returned by CheckedFolderBs method newCheck1o(Model. =or the second goal (auto select/unselect children and ancestor nodes) we can use CheckedFolderBs callbac# method on9pdate(A5a()e6"est/arget that is in.o#ed after a chec#bo, is clic#ed and its .alue has been updated. @.erriding this method we can handle user clic# adding/remo.ing nodes to/from the Ka.a Set. =ollowing this implementation plan we can start coding our custom CheckedFolder (named A"tocheckedFolder)(
public class 5utochecked3older<T> extends Checked3older<T> pri4ate $Tree#ro4ider<T> tree#ro4ider1 pri4ate $;odel<)et<T>> checkedNodes1 pri4ate $;odel<.oolean> checkbox;odel1 public 5utochecked3older7)tring id, 5bstractTree<T> tree, $;odel<T> model, $;odel<)et<T>> checkedNodes: super7id, tree, model:1 this.tree#ro4ider 8 tree.get#ro4ider7:1 this.checkedNodes 8 checkedNodes1 & !'4erride protected $;odel<.oolean> neCCheck.ox;odel7$;odel<T> model: checkbox;odel 8 & !'4erride protected 4oid on0pdate752ax*eEuestTarget target: super.on0pdate7target:1 T node 8 get;odel'b2ect7:1 boolean nodeChecked 8 checkbox;odel.get'b2ect7:1 add*emo4e)ubNodes7node, nodeChecked:1 add*emo4e5ncestorNodes7node, nodeChecked:1 & neC Check;odel7:1 return checkbox;odel1

Wicket free user guide

1A$

18 Working with 7)7?

class Check;odel extends 5bstractCheck.ox;odel !'4erride public boolean is)elected7: return checkedNodes.get'b2ect7:.contains7get;odel'b2ect7::1 & !'4erride public 4oid select7: checkedNodes.get'b2ect7:.add7get;odel'b2ect7::1 & !'4erride public 4oid unselect7: checkedNodes.get'b2ect7:.remo4e7get;odel'b2ect7::1 & & &

The constructor of this new component ta#es in input a further parameter which is the set containing chec#ed nodes. !lass CheckModel is the custom model we ha.e implemented for chec#bo, control. As base class for this model we ha.e used AbstractCheck1o(Model which is pro.ided to implement custom models for chec#bo, controls. <ethods add)emo!eS"bNodes and add)emo!eAncestorNodes are called to automatically add/remo.e children and ancestor nodes to/from the current Set. Their implementation is mainly focused on the na.igation of tree nodes and it hea.ily depends on the internal implementation of the tree* so we wonBt dwell on their code. ow we are Hust one step away from completing our tree as we still ha.e to find a way to update the chec#ed status of both children and ancestors nodes on client side. Although we could easily accomplish this tas# by simply refreshing the whole tree .ia AKAL* we would li#e to find a better and more performant solution for this tas#. 2hen we modify the chec#ed status of a node we donBt e,pand/collapse any node of the three so we can simply update the desired chec#bo,es rather than updating the entire tree component. This alternati.e approach could lead to a more responsi.e interface and to a strong reduction of bandwidth consumption. 2ith the help of KQuery we can code a couple of Ka.a"cript functions that can be used to chec#/ unchec# all the children and ancestors of a gi.en node. Then* we can append these functions to the current A5a()e6"est at the end of method on9pdate(

!'4erride protected 4oid on0pdate752ax*eEuestTarget target: super.on0pdate7target:1 T node 8 get;odel'b2ect7:1 boolean nodeChecked 8 checkbox;odel.get'b2ect7:1 add*emo4e)ubNodes7node, nodeChecked:1 add*emo4e5ncestorNodes7node, nodeChecked:1 updateNode'nClient)ide7target, nodeChecked:1 &

Wicket free user guide

1A3

18 Working with 7)7?

protected 4oid updateNode'nClient)ide752ax*eEuestTarget target, boolean nodeChecked: target.appendLa4a)cript791Check5ncestors5ndChildren.checkChildren7I9 > get;arkup$d7: > 9I,9 > nodeChecked > 9:19:1 target.appendLa4a)cript791Check5ncestors5ndChildren.check5ncestors7I9 > get;arkup$d7: > 9I,9 > nodeChecked > 9:19:1 &

The Ka.a"cript code can be found inside file section as pac#age resource(
!'4erride

autochecked3older.2s

which is added to the header

public 4oid renderDead7$Deader*esponse response: #ackage*esource*e%erence script3ile 8 neC #ackage*esource*e%erence7this.getClass7:, 9autochecked3older.2s9:1 response.render7La4a)criptDeader$tem.%or*e%erence7script3ile::1 &

1-.2.2

Working with hidden components

2hen a component is not .isible its mar#up and the related id attribute are not rendered in the final page* hence it can not be updated .ia AKAL. To o.ercome this problem we must use ComponentBs method set+"tp"tMark"pPlaceholder/ag(tr"e which has the effect of rendering a hidden <span> tag containing the mar#up id of the hidden component(
%inal /abel label 8 neC /abel79labelComponent9, 9$nitial 4alue.9:1 //make label in4isible label.setOisible7%alse:1 //ensure that label Cill lea4e a placeholder %or its markup id label.set'utput;arkup#laceholderTag7 true:1 add7label:1 //... neC 52ax/ink79a2ax/ink9: !'4erride public 4oid onClick752ax*eEuestTarget target: //turn label to 4isible label.setOisible7true:1 target.add7label:1 & &1

Please note that in the code abo.e we didnBt in.o#ed method set+"tp"tMark"p2d(tr"e set+"tp"tMark"pPlaceholder/ag already does it internally.

as

1-.3 ;uilt?in A7A9 *ehaviors


-n addition to specific components* 2ic#et offers also a set of built in AKAL beha.iors that can be used to easily add AKAL functionalities to e,isting components. As we will see in this paragraph AKAL beha.iors can be used also to aHa,ify components that werenBt initially designed to wor# with this technology. All the following beha.iors are inside pac#age org.apache.wicket.a5a(.

1-.3.1

A<axDvent;ehavior

Wicket free user guide

1A5

18 Working with 7)7?

A5a('!ent1eha!ior allows to handle a Ka.a"cript e.ent (li#e clic#* change* etc...) on ser.er side .ia AKAL. -ts constructor ta#es in input the name of the e.ent that must be handled. I.ery time this e.ent is fired for a gi.en component on client side* the callbac# method on'!ent(A5a()e6"est/arget target is e,ecuted. on'!ent is abstract* hence we must implement it to tell A5a('!ent1eha!ior what to do when the specified e.ent occurs. -n proHect $-a0#vent9ehavior#0ample we used this beha.ior to build a Fclic#ableG Label component that counts the number of clic#s. 9ere is the code from the home page of the proHect( 9tml(
<bod"> <di4 Cicket:id89clickCounter/abel9></di4> 0ser has clicked <span Cicket:id89clickCounter9></span> time/s on the label abo4e. </bod">

Ka.a code(
public class Dome#age extends Web#age public Dome#age7%inal #age#arameters parameters: super7parameters:1 %inal ClickCounter/abel clickCounter/abel 8 neC ClickCounter/abel79clickCounter/abel9, 9Click on meF9:1 %inal /abel clickCounter 8 neC /abel79clickCounter9, neC #ropert";odel7clickCounter/abel, 9clickCounter9::1

clickCounter/abel.set'utput;arkup$d7true:1 clickCounter/abel.add7neC 52ax(4ent.eha4ior79click9: !'4erride protected 4oid on(4ent752ax*eEuestTarget target: clickCounter/abel.clickCounter>>1 target.add7clickCounter:1 & &:1 add7clickCounter/abel:1 add7clickCounter.set'utput;arkup$d7true::1 & & class ClickCounter/abel extends /abel public int clickCounter1 public ClickCounter/abel7)tring id: super7id:1 & public ClickCounter/abel7)tring id, $;odel<?> model: super7id, model:1 & public ClickCounter/abel7)tring id, )tring label: super7id, label:1

Wicket free user guide

1AA

18 Working with 7)7?

& &

-n the code abo.e we ha.e declared a custom label class named ClickCo"nterLabel that e,poses a public integer field called clickCounter. Then* in the home page we ha.e attached a A5a('!ent1eha!ior to our custom label to increment clickCounter e.ery time it recei.es a clic# e.ent. The number of clic#s is displayed with another standard label named clickCounter.

1-.3.2

A<axHorm8u=mit;ehavior

This beha.ior allows to send a form .ia AKAL when the component it is attached to recei.es the specified e.ent. The component doesnBt need to be inside the form if we use the constructor .ersion that* in addition to the name of the e.ent* ta#es in input also the target form(
3orm %orm 8 neC 3orm79%orm9:1 .utton submit.utton 8 neC .utton79submit.utton9:1 //submit %orm Chen button is clicked submit.utton.add7neC 52ax3orm)ubmit.eha4ior7%orm, 9click9: &:1 add7%orm:1 add7submit.utton:1

1-.3.3

A<axHorm.omponent0pdating;ehavior

This beha.ior updates the model of the form component it is attached to when a gi.en e.ent occurs. The standard form submitting process is s#ipped and the beha.ior .alidates only its form component. The beha.ior doesnBt wor# with radio buttons and chec#bo,es. =or these #inds of components we must use A5a(FormChoiceComponent9pdating1eha!ior(
3orm %orm 8 neC 3orm79%orm9:1 Text3ield text3ield 8 neC Text3ield79text3ield9, ;odel.o%799::1 //update the model o% the text %ield each time e4ent 9change9 occurs text3ield.add7neC 52ax3ormComponent0pdating.eha4ior79change9: !'4erride protected 4oid on0pdate752ax*eEuestTarget target: //... & &:1 add7%orm.add7text3ield::1

1-.3.#

A=stractA<ax*imer;ehavior

AbstractA5a(/imer1eha!ior e,ecutes callbac# method on/imer(A5a()e6"est/arget target at a specified inter.al. The beha.ior can be stopped and restarted at a later time with methods stop(A5a()e6"est/arget target and restart(A5a()e6"est/arget target (
/abel d"namic/abel 8 neC /abel79d"namic/abel9:1 //trigger an 5L5] reEuest e4er" three seconds d"namic/abel.add7neC 5bstract52axTimer.eha4ior7+uration.seconds7R:: !'4erride protected 4oid onTimer752ax*eEuestTarget target: //... & &:1

Wicket free user guide

1A6

18 Working with 7)7?

add7d"namic/abel:1

1-.# 0sing an activit indicator


@ne of the thing we must ta#e care of when we use AKAL is to notify user when an AKAL reEuest is already in progress. This is usually done displaying an animated picture as acti.ity indicator while the AKAL reEuest is running. 2ic#et comes with a .ariant of components A5a(1"tton* A5a(Link and A5a(FallbackLink that display a default acti.ity indicator during AKAL reEuest processing. These components are respecti.ely 2ndicatingA5a(1"tton* 2ndicatingA5a(Link and 2ndicatingA5a(FallbackLink. The default acti.ity indicator used in 2ic#et can be easily integrated in our components using beha.ior A5a(2ndicatorAppender (a.ailable in pac#age org.apache.wicket.e(tensions.a5a(. mark"p.html) and implementing the interface 2A5a(2ndicatorAware (in pac#age org.apache. wicket.a5a(). 2A5a(2ndicatorAware declares method getA5a(2ndicatorMark"p2d( which returns the id of the mar#up element used to display the acti.ity indicator. This id can be obtained from the A5a(2ndicatorAppender beha.ior that has been added to the current component. The following code snippet summariCes the steps needed to integrate the default acti.ity indicator with an aHa,ified component(
//@-$mplement inter%ace $52ax$ndicator5Care public class ;"Component extends Component implements $52ax$ndicator5Care //=-$nstantiate an 52ax$ndicator5ppender pri4ate 52ax$ndicator5ppender indicator5ppender 8 neC 52ax$ndicator5ppender7:1 public ;"Component7)tring id, $;odel<?> model: super7id, model:1 //R-5dd the 52ax$ndicator5ppender to the component add7indicator5ppender:1 & //<-*eturn the markup id obtained %rom 52ax$ndicator5ppender public )tring get52ax$ndicator;arkup$d7: return indicator5ppender.get;arkup$d7:1 & //... &

-f we need to change the default picture used as acti.ity indicator* we can o.erride method get2ndicator9rl( of A5a(2ndicatorAppender and return the &+: to the desired picture.

1-.( A<ax re1uest attri=utes and call listeners


"tarting from .ersion A.% 2ic#et has introduced two entities which allow us to control how an AKAL reEuest is generated on client side and to specify the custom Ka.a"cript code we want to e,ecute during reEuest handling. These entities are class A5a()e6"estAttrib"tes and interface 2A5a(CallListener* both placed in pac#age org.apache.wicket.a5a(.attrib"tes. A5a()e6"estAttrib"tes e,poses the attributes used to generate the Ka.a"cript call in.o#ed on client side to start an AKAL reEuest. Iach attribute will be passed as a K"@ 55 parameter to the Ka.a"cript function Wicket.A5a(.a5a( which is responsible for sending the concrete AKAL reEuest. I.ery K"@ parameter is identified by a short name. 9ere is a partial list of the a.ailable parameters(
55 http%CCen$wikipedia$orgCwikiC)'"K

Wicket free user guide

1A7

18 Working with 7)7?

8hort name u c e m f mp sc async wr

5escription The callbac# &+: used to ser.e the AKAL reEuest that will be sent. The id of the component that wants to start the AKAL call. A list of e.ent (clic#* change* etc...) that can trigger the AKAL call. The reEuest method that must be used (0IT or P@"T). The id of the form that must be submitted with the AKAL call. -f the AKAL call in.ol.es the submission of a form* this flag indicates whether the data must be encoded using the encoding mode Fmultipart/form-dataG. The input name of the submitting component of the form A boolean parameter that indicates if the AKAL call is asynchronous (true ) or not. "pecifies the type of data returned by the AKAL call (L<:* 9T<:* K"@ * etc...).

5efault value

domready 0IT

%alse

true

L<:

This is a list of the listeners that are e,ecuted on client side (they are bh* pre* bsh* Ka.a"cript scripts) during the lifecycle of an AKAL reEuest. Iach ah* sh* fh* short name is the abbre.iation of one of the methods defined in the coh interface 2A5a(CallListener (see below). >ote

An empty list

A full list of the a.ailable reEuest parameters as well as more details on the related Ka.a"cript code can be found at https(//cwi#i.apache.org/confluence/ display/2-!MIT/2ic#etNAHa,. Parameters BuB (callbac# &+:) and BcB (the id of the component) are generated by the AKAL beha.ior that will ser.e the AKAL call and they are not accessible through A5a()e6"estAttrib"tes. 9ere is the final AKAL function generate for the beha.ior used in e,ample proHect $-a0#vent9ehavior #0ample:
Wicket.52ax.a2ax7 9u9:9./?A-@.$.eha4ior/istener.A-clickCounter/abel9,9e9:9click9, 9c9:9clickCounter/abel@9&:1

I.en if most of the times we will let 2ic#et generate reEuest attributes for us* both AKAL components and beha.iors gi.e us the chance to modify them o.erriding their method "pdateA5a(Attrib"tes (A5a()e6"estAttrib"tes attrib"tes . @ne of the attribute we may need to modify is the list of 2A5a(CallListeners returned by method getA5a(CallListeners( . 2A5a(CallListener defines a set of methods which return the Ka.a"cript code (as a CharSe6"ence) that must be e,ecuted on client side when the AKAL reEuest handling reaches a gi.en stage( get;eforeHandlerJ.omponent@( returns the Ka.a"cript code that will be e,ecuted before any other handlers returned by 2A5a(CallListener. The code is e,ecuted in a scope where it can use .ariable attrs* which is an array containing
Wicket free user guide

1A8

18 Working with 7)7?

the K"@ parameters passed to Wicket.A5a(.a5a(. getPreconditionJ.omponent@( returns the Ka.a"cript code that will be used as precondition for the AKAL call. -f the script returns false then neither the AHa, call nor the other handlers will be e,ecuted. The code is e,ecuted in a scope where it can use .ariable attrs* which is the same .ariable seen for get1e0oreHandler. get;efore8endHandlerJ.omponent@( returns the Ka.a"cript code that will be e,ecuted Hust before the AKAL call is performed. The code is e,ecuted in a scope where it can use .ariables attrs* 2E]D* and settings( - attrs is the same .ariable seen for get1e0oreHandler. - 2E]D* is the the HQuery L<:9ttp+eEuest obHect used to ma#e the AKAL call. - settings contains the settings used for calling HQuery.aHa,(). getAfterHandlerJ.omponent@( returns the Ka.a"cript code that will be e,ecuted after the AKAL call. The code is e,ecuted in a scope where it can use .ariable attrs* which is the same .ariable seen before for get1e0oreHandler. get8uccessHandlerJ.omponent@( returns the Ka.a"cript code that will be e,ecuted if the AKAL call has successfully returned. The code is e,ecuted in a scope where it can use .ariables attrs* 2E]D** data and text)tatus( - attrs and 2E]D* are same .ariables seen for get1e0oreSendHandler( - data is the data returned by the AKAL call. -ts type depends on parameter Cr (2ic#et AKAL response). - text)tatus itBs the status returned as te,t. getHailureHandlerJ.omponent@( returns the Ka.a"cript code that will be e,ecuted if the AKAL call has returned with a failure. The code is e,ecuted in a scope where it can use .ariable attrs* which is the same .ariable seen for get1e0oreHandler. get.ompleteHandlerJ.omponent@( returns the Ka.a"cript that will be in.o#ed after success or failure handler has been e,ecuted. The code is e,ecuted in a scope where it can use .ariables attrs* 2E]D* and text)tatus which are the same .ariables seen for getS"ccessHandler.

-n the ne,t paragraph we will see an e,ample of custom 2A5a(CallListener designed to disable a component during AKAL reEuest processing.

1-.- .reating custom A7A9 call listener


Displaying an acti.ity indicator is a nice way to notify user that an AKAL reEuest is already running* but sometimes is not enough. -n some situations we may need to completely disable a component during AKAL reEuest processing* for e,ample when we want to a.oid that impatient users submit a form multiple times. -n this paragraph we will see how to accomplish this goal building a custom and reusable 2A5a(CallListener. The code used in this e,ample is from proHect (ustom$-a0%istener#0ample.

1-.-.1

What we want for our listener

The listener should e,ecute some Ka.a"cript code to disable a gi.en component when the component it is attached to is about to ma#e an AKAL call. Then* when the AKAL reEuest has been completed* the listener should bring bac# the disabled component to an acti.e state. 2hen a component is disabled it must be clear to user that an AKAL reEuest is running and that he/she must wait for it to complete. To achie.e this result we want to disable a gi.en component co.ering it with a semi-transparent o.erlay area with an acti.ity indicator in the middle. The final result will loo# li#e this(
Wicket free user guide

16%

18 Working with 7)7?

llustration 18$8% The overlay area on a form 4from pro#ect Custom7#axBehaviorHxample5

1-.-.2

How to implement the listener

The listener will implement methods get1e0oreHandler and getA0terHandler( the first will return the code needed to place an o.erlay <di4> on the desired component while the second must remo.e this o.erlay when the AKAL call has completed. To mo.e and resiCe the o.erlay area we will use another module from KQuery&- library that allows us to position D@< elements on our page relati.e to another element 5A. "o our listener will depend on four static resources( the KQuery library* the position module of KQuery &-* the custom code used to mo.e the o.erlay <di4> and the picture used as acti.ity indicator. I,cept for the acti.ity indicator* all these resources must be added to page header section in order to be used. AHa, call listeners can contribute to header section by simply implementing interface 2ComponentAwareHeaderContrib"tor. 2ic#et pro.ides adapter class A5a(CallListener that implements both 2A5a(CallListener and 2ComponentAwareHeaderContrib"tor. 2e will use this class as base class for our listener.

1-.-.3

7ava8cript code

ow that we #now what to do on the Ka.a side* letBs ha.e a loo# at the custom Ka.a"cript code that must be returned by our listener (file mo.e9iderAnd-ndicator.Hs)(
+isableComponent/istener 8 disable(lement: %unction7element$d, acti4e$con0rl: 4ar hider$d 8 element$d > 9-disable-la"er91 4ar indicator$d 8 element$d > 9-indicator-picture91 element$d 8 9X9 > element$d1 //create the o4erla" <di4> W7element$d:.a%ter7I<di4 id89I > hider$d > I9 st"le89position:absolute19>I > I<img id89I > indicator$d > > I</di4>I:1 hider$d 8 9X9 > hider$d1 //set the st"le properties o% the o4erla" <di4> W7hider$d:.css7Iopacit"I, IA.BI:1 W7hider$d:.css7Itext-alignI, IcenterI:1 W7hider$d:.css7Ibackground-colorI, IWhite)mokeI:1 W7hider$d:.css7IborderI, I@px solid +ark-ra"I:1 //set the dimention o% the o4erla" <di4> W7hider$d:.Cidth7W7element$d:.outerWidth7::1 W7hider$d:.height7W7element$d:.outerDeight7::1
56 http: -5ueryui.com position

I9 src89I > acti4e$con0rl > I9/>I

Wicket free user guide

161

18 Working with 7)7?

//positioning the o4erla" <di4> on the component that must be disabled. W7hider$d:.position7 o%: W7element$d:,at: Itop le%tI, m": Itop le%tI&:1 //positioning the acti4it" indicator in the middle o% the o4erla" <di4> W79X9 > indicator$d:.position7 o%: W7hider$d:, at: Icenter centerI, m": Icenter centerI&:1 &, //%unction hideComponent

=unction +isableComponent/istener.disable(lement places the o.erlay <di4> an the acti.ity indicator on the desired component. The parameters in input are the mar#up id of the component we want to disable and the &+: of the acti.ity indicator picture. These two parameters must be pro.ided by our custom listener. The rest of custom Ka.a"cript contains function +isableComponent/istener.hideComponent which is Hust a wrapper around the KQuery function remo4e7::
hideComponent: %unction7element$d: 4ar hider$d 8 element$d > 9-disable-la"er91 W7IXI > hider$d:.remo4e7:1 & &1

1-.-.#

.lass code

The code of our custom listener is the following(


public class +isableComponent/istener extends 52axCall/istener pri4ate static #ackage*esource*e%erence custom)cript*e%erence 8 neC #ackage*esource*e%erence7+isableComponent/istener.class,9mo4eDider5nd$ndicator.2s9:1 pri4ate static #ackage*esource*e%erence 2Euer"0i#osition*e% 8 neC #ackage*esource*e%erence7+isableComponent/istener.class, 92Euer"-ui-position.min.2s9:1 pri4ate static #ackage*esource*e%erence indicator*e%erence 8 neC #ackage*esource*e%erence7+isableComponent/istener.class, 9a2ax-loader.gi%9:1 pri4ate Component targetComponent1 public +isableComponent/istener7Component targetComponent: this.targetComponent 8 targetComponent1 & !'4erride public Char)eEuence get.e%oreDandler7Component component: Char)eEuence indicator0rl 8 get$ndicator0rl7component:1 return 91+isableComponent/istener.disable(lement7I9 > targetComponent.get;arkup$d7: > 9I,9 > 9I9 > indicator0rl > 9I:191 & !'4erride public Char)eEuence getCompleteDandler7Component component: return 91+isableComponent/istener.hideComponent7I9 > targetComponent.get;arkup$d7: > 9I:191 &

Wicket free user guide

164

18 Working with 7)7?

protected Char)eEuence get$ndicator0rl7Component component: return component.url3or7indicator*e%erence, null:1 & !'4erride public 4oid renderDead7Component component, $Deader*esponse response: *esource*e%erence 2Euer"*e%erence 8 5pplication.get7:.getLa4a)cript/ibrar")ettings7:. getLVuer"*e%erence7:1 response.render7La4a)criptDeader$tem.%or*e%erence72Euer"*e%erence::1 response.render7La4a)criptDeader$tem.%or*e%erence72Euer"0i#osition*e%::1 response.render7La4a)criptDeader$tem.%or*e%erence7custom)cript*e%erence::1 & &

As you can see in the code abo.e we ha.e created a function ( get2ndicator9rl) to retrie.e the &+: of the indicator picture. This was done in order to ma#e the picture customiCable by o.erriding this method. @nce we ha.e our listener in place* we can finally use it in our e,ample o.erwriting method "pdateA5a(Attrib"tes of the AKAL button that submits the form(
//... neC 52ax.utton79a2ax.utton9: !'4erride protected 4oid update52ax5ttributes752ax*eEuest5ttributes attributes: super.update52ax5ttributes7attributes:1 attributes.get52axCall/isteners7:.add7neC +isableComponent/istener7%orm::1 & & //...

1-.-.(

Glo=al listeners

"o far we ha.e seen how to use an AKAL call listener to trac# the AKAL acti.ity of a single component. -n addition to these #inds of listeners* 2ic#et pro.ides also global listeners which are triggered for any AKAL reEuest sent from a page. 0lobal AKAL call e.ents are handled with Ka.a"cript. 2e can register a callbac# function for a specific e.ent of the AKAL call lifecycle with function Wicket.(4ent.subscribe7I<e4entName>I, <callback 3unction>:. The first parameter of this function is the name of the e.ent we want to handle. The possible names are( I/a2ax/call/be%oreI( called before any other e.ent handler. I/a2ax/call/be%ore)endI( called Hust before the AKAL call. I/a2ax/call/a%terI( called after the AKAL reEuest has been sent. I/a2ax/call/successI( called if the AKAL call has successfully returned. I/a2ax/call/%ailureI( called if the AKAL call has returned with a failure. I/a2ax/call/completeI( called when the AKAL call has completed. I/dom/node/remo4ingI( called when a component is about to be remo.ed .ia AKAL. This happens when component mar#up is updated .ia AKAL (i.e. the component itself or one of its containers has been added to A5a()e6"est/arget) I/dom/node/addedI( called when a component has been added .ia AKAL. Kust li#e I/dom/node/remo4ingI* this e.ent is triggered when a component is added to A5a()e6"est

Wicket free user guide

16$

18 Working with 7)7?

/arget. The callbac# function ta#es in input the following parameters( attrs* 2E]D** text)tatus* 2E(4ent and The first three parameters are the same seen before with 2A5a(CallListener while 2E(4ent is an e.ent internally fired by 2ic#et. The last parameter errorThroCn indicates if an error has occurred during the AKAL call. To see a basic e,ample of use of a global AKAL call listener* letBs go bac# to our custom datepic#er created in chapter 13. 2hen we built it we didnBt thin# about a possible use of the component with AKAL. 2hen a comple, component li#e our datepic#er is refreshed .ia AKAL* the following two side effects can occur( After been refreshed* the component loses e.ery Ka.a"cript handler set on it. This is not a problem for our datepic#er as it sets a new KQuery datepic#er e.ery time is rendered (inside method renderHead). The mar#up pre.iously created with Ka.a"cript is not remo.ed. =or our datepic#er this means that the icon used to open the calendar wonBt be remo.ed while a new one will be added each time the component is refreshed.
errorThroCn.

To sol.e the second unwanted side effect we can register a global AKAL call listener that completely remo.es the datepic#er functionality from our component before it is remo.ed due to an AKAL refresh (which fires e.ent I/dom/node/remo4ingI). ProHect !ustomDatepic#erAHa, contains a new .ersion of our datepic#er which adds to its Ka.a"cript file KQDatePic#er.Hs the code needed to register a callbac# function that gets rid of the KQuery datepic#er before the component is remo.ed from the D@<(
Wicket.(4ent.subscribe7I/dom/node/remo4ingI, %unction72E(4ent, attributes, 2E]D*, errorThroCn, text)tatus: 4ar component$d 8 IXI > attributesHIidIJ1 i%7W7component$d:.datepicker F88 unde%ined: W7component$d:.datepicker7Idestro"I:1 & :1

The code abo.e retrie.es the id of the component that is about to be remo.ed using parameter attributes. Then it chec#s if a KQuery datepic#er was defined for the gi.en component and if so* it remo.es the widget calling function destro".

1-.' 8ummar
AKAL is another e,ample of how 2ic#et can simplify web technologies pro.iding a good component and obHect oriented abstraction of them. -n this chapter we ha.e seen how to ta#e ad.antage of the AKAL support pro.ided by 2ic#et to write AKAL-enhanced applications. <ost of the chapter has been dedicated to the built-in components and beha.iors that let us adopt AKAL without almost any effort. -n the final part of the chapter we ha.e seen how 2ic#et physically implements an AKAL call on client side using AKAL reEuest attributes. Then* we ha.e learnt how to use call listeners to e,ecute custom Ka.a"cript during AKAL reEuest lifecycle.

Wicket free user guide

163

12 ntegration with enterprise containers

1) Integration with enterprise containers


2riting a web application is not Hust about producing a good layout and a bunch of FcoolG pages. 2e must also integrate our presentation code with enterprise resources li#e data sources* message Eueues* business obHects* etc... The first decade of 4%%%s has seen the rising of new framewor#s (li#e "pring56) and new specifications (li#e IKB $.157) aimed to simplify the management of enterprise resources and (among other things) their integration with presentation code. All these new technologies are based on the concepts of container and dependency in-ection. (ontainer is the en.ironment where our enterprise resources are created and configured while dependency in-ection58 is a pattern implemented by containers to in-ect into an obHect the resources it depends on. 2ic#et can be easily integrated with enterprise containers using component instantiation listeners. These entities are instances of interface org.apache.wicket.application.2Component 2nstantiationListener and can be registered during applicationBs initialiCation. 2Component2nstantiationListener defines callbac# method on2nstantiation(Component component which can be used to pro.ide custom instantiation logic for 2ic#et components. 2ic#et distribution and proHect 2ic#et"tuffA% already pro.ide a set of built-in listeners to integrate our applications with IKB $.1 compliant containers (li#e KBoss "eamA1) or with some of the most popular enterprise framewor#s li#e 0uiceA4 or "pring. -n this chapter we will see two basic e,amples of inHecting a container-defined obHect into a page using first an implementation of the IKB $.1 specifications (proHect @penIKBA$) and then using "pring.

1'.1 !ntegrating Wicket with D7;


2ic#et"tuff pro.ides a module called wicketst"00@5a!aee@in5ect that contains component instantiation listener .a!a''Component2n5ector. -f we register this listener in our application we can use standard IKB annotations to inHect dependencies into our 2ic#et components. To register a component instantiation listener in 2ic#et we must use ApplicationBs method getComponent2nstantiationListeners which returns a typed collection of 2Component 2nstantiationListeners. The following initialiCation code is ta#en from proHect #-bIn-ection#0ample(
public class Wicket5pplication extends Web5pplication //Constructor... !'4erride public 4oid init7:

57 58 59 60 61 62 63

http: www.springsource.org http: en.wikipedia.org wiki #nterprise13ava9eans http: en.wikipedia.org wiki @ependency1In-ection https: github.com wicketstuff 7n overview of Wicket'tuff pro#ect is available in 7ppendix B 'eam has its own integration module for Wicket6 but it is stuck on Wicket version 1$3 http: code.google.com p google*guice http: opene-b.apache.org

Wicket free user guide

165

12 ntegration with enterprise containers

super.init7:1 getComponent$nstantiation/isteners7:.add7neC La4a((Component$n2ector7this::1 & &

-n this e,ample the obHect that we want to inHect is a simple class containing a greeting message(
!;anaged.ean public class (nterprise;essage public )tring message 8 9Welcome to the (L. CorldF91 &

Please note that we ha.e used annotation !;anaged.ean to decorate our obHect. ow to inHect it into the home page we must add a field of type 'nterpriseMessage and annotate it with annotation !(L.(
public class Dome#age extends Web#age !(L. pri4ate (nterprise;essage enterprise;essage1 //getter and setter %or enterprise;essage... public Dome#age7%inal #age#arameters parameters: super7parameters:1 add7neC /abel79message9, enterprise;essage.message::1 & &

That is all. 2e can point the browser to the home page of the proHect and see the greeting message inHected into the page(

1'.2 !ntegrating Wicket with 8pring


-f we need to inHect dependencies with "pring we can use listener org.apache.wicket.spring. in5ection.annot.SpringComponent2n5ector pro.ided by module Cicket-spring. =or the sa#e of simplicity in the e,ample proHect SpringIn-ection#0ample we ha.e used "pring class AnnotationCon0igApplicationConte(t to a.oid any L<: file and create a "pring conte,t directly from code(
public class Wicket5pplication extends Web5pplication //Constructor... !'4erride

Wicket free user guide

16A

12 ntegration with enterprise containers

public 4oid init7: super.init7:1 5nnotationCon%ig5pplicationContext ctx 8 neC 5nnotationCon%ig5pplicationContext7:1 //)can package %or annotated beans ctx.scan79org.CicketTutorial.e2b.ean9:1 ctx.re%resh7:1 getComponent$nstantiation/isteners7:.add7neC )pringComponent$n2ector7this, ctx::1 & &

As we can see in the code abo.e* the constructor of SpringComponent2n5ector ta#es in input also an instance of "pring conte,t. The inHected obHect is the same used in the pre.ious proHect #-bIn-ection#0ample* it differs only for the greeting message(
!;anaged.ean public class (nterprise;essage public )tring message 8 9Welcome to the )pring CorldF91 &

-n the home page of the proHect the obHect is inHected using 2ic#et annotation !)pring.ean(
public class Dome#age extends Web#age !)pring.ean pri4ate (nterprise;essage enterprise;essage1 //getter and setter %or enterprise;essage... public Dome#age7%inal #age#arameters parameters: super7parameters:1 add7neC /abel79message9, enterprise;essage.message::1 & &

By default !)pring.ean searches into "pring conte,t for a bean ha.ing the same type of the annotated field. -f we want we can specify also the name of the bean to use as inHected obHect and we can declare if the dependency is reEuired or not. By default dependencies are reEuired and if they can not be resol.ed to a compatible bean* 2ic#et will throw an 2llegalState'(ception(
//set the dependenc" as not reEuired, i.e the %ield can be le%t null !)pring.ean7name89anotherName9, reEuired8%alse: pri4ate (nterprise;essage enterprise;essage1

1'.3 783?33/-# annotations


"pring (and 0uice) users can use standard K"+-$$% annotations to wire their dependencies. This will ma#e their code more interoperable with other containers that support this standard(
64 http: -cp.org en -sr detailHidI==,

Wicket free user guide

166

12 ntegration with enterprise containers

//in2ect a bean speci%"ing its name Cith L)*-RRA annotations !$n2ect !Named79anotherName9: pri4ate (nterprise;essage enterprise;essage1

1'.# 8ummar
-n this chapter we ha.e seen how to integrate 2ic#et applications with "pring and with an IKB container. <odule Cicket-examples contains also an e,ample of integration with 0uice (see application class org.apache.wicket.e(amples.g"ice.*"iceApplication).

Wicket free user guide

167

1= 'ecurity with Wicket

1, 4ecurity with Wicket


"ecurity is one of the most important non-functional reEuirements we must implement in our applications. This is particularly true for enterprise applications as they usually support multiple concurrent users* and therefore they need to ha.e an access control policy. -n this chapter we will e,plore the security infrastructure pro.ided by 2ic#et and we will learn how to use it to implement authentication and authoriCations in our web applications.

12.1 Authentication
The first step in implementing a security policy is assigning a trusted identity to our users* which means that we must authenticate them. 2eb applications usually adopt a form-based authentication with a login form that as#s user for a uniEue username and the relati.e password(

llustration 1=$1% 0ogin form from Wikipedia 2ic#et supports form-based authentication with session class A"thenticatedWebSession and application class A"thenticatedWebApplication* both placed inside pac#age org.apache. wicket.a"throles.a"thentication.

12.1.1

AuthenticatedWe=8ession

!lass A"thenticatedWebSession comes with the following set of public methods to manage user authentication( authenticateJ8tring usernameG 8tring password@ ( this is an abstract method that must be implemented by e.ery subclass of A"thenticatedWebSession. -t should contain the actual code that chec#s for userBs identity. -t returns a boolean .alue which is tr"e if authentication has succeeded or 0alse otherwise. sign!nJ8tring usernameG 8tring password@( this method internally calls a"thenticate and set the flag signed$n to tr"e if authentication succeeds. is8igned!nJ@(getter method for flag signed$n. signCutJ@( sets the flag signed$n to 0alse. invalidateJ@( calls sign+"t and in.alidates session. Warning +emember that sign+"t does not discard any session-relati.e data. -f we want to get rid of these data* we must in.o#e method in!alidate instead of sign+"t.

Wicket free user guide

168

1= 'ecurity with Wicket

Another abstract method we must implement when we use A"thenticatedWebSession is get)oles which is inherited from parent class AbstractA"thenticatedWebSession. This method can be ignored for now as it will be discussed later when we will tal# about role-based authoriCation.

12.1.2

AuthenticatedWe=Application

!lass A"thenticatedWebApplication pro.ides the following methods to support form-based authentication( getWe=8ession.lassJ@( abstract method that returns the session class to use for this application. The returned class must be a subclass of AbstractA"thenticatedWeb Session. get8ign!nPage.lassJ@( abstract method that returns the page to use as sign in page when a user must be authenticated. restart3esponseAt8ign!nPageJ@( forces the current response to restart at the sign in page. After we ha.e used this method to redirect a user* we can ma#e her/him return to the original page calling ComponetBs method contin"e/o+riginal:estination( . The other methods implemented inside A"thenticatedWebApplication will be introduced when we will tal# about authoriCations.

12.1.3

A =asic example of authentication.

ProHect 9asic$uthentication#0ample is a basic e,ample of form-based authentication implemented with classes A"thenticatedWebSession and A"thenticatedWebApplication. The homepage of the proHect contains only a lin# to page A"thenticatedPage which can be accessed only if user is signed in. The code of A"thenticatedPage is this following(
public class 5uthenticated#age extends Web#age !'4erride protected 4oid onCon%igure7: 5uthenticatedWeb5pplication app 8 75uthenticatedWeb5pplication:5pplication.get7:1 //i% user is not signed in, redirect him to sign in page i%7F5uthenticatedWeb)ession.get7:.is)igned$n7:: app.restart*esponse5t)ign$n#age7:1 & !'4erride protected 4oid on$nitialiPe7: super.on$nitialiPe7:1 add7neC /ink79goToDome#age9: !'4erride public 4oid onClick7: set*esponse#age7get5pplication7:.getDome#age7::1 & &:1 add7neC /ink79log'ut9: !'4erride public 4oid onClick7: 5uthenticatedWeb)ession.get7:.in4alidate7:1 set*esponse#age7get5pplication7:.getDome#age7::1 &

Wicket free user guide

17%

1= 'ecurity with Wicket

&:1 & &

Page A"thenticatedPage chec#s inside onCon0ig"re if user is signed in and if not* it redirects her/him to the sign in page with method restart)esponseAtSign2nPage. The page contains also a lin# to the homepage and another lin# that signs out user. The sign in page is implemented in class Sign2nPage and contains the form used to authenticate users(
public class )ign$n#age extends Web#age pri4ate )tring username1 pri4ate )tring passCord1 !'4erride protected 4oid on$nitialiPe7: super.on$nitialiPe7:1 )tateless3orm %orm 8 neC )tateless3orm79%orm9: !'4erride protected 4oid on)ubmit7: i%7)trings.is(mpt"7username:: return1 boolean auth*esult 8 5uthenticatedWeb)ession.get7:.sign$n7username, passCord:1 //i% authentication succeeds redirect user to the reEuested page i%7auth*esult: continueTo'riginal+estination7:1 & &1 %orm.set+e%ault;odel7neC Compound#ropert";odel7this::1 %orm.add7neC Text3ield79username9::1 %orm.add7neC #assCordText3ield79passCord9::1 add7%orm:1 & &

The form is responsible for handling user authentication inside its method onS"bmit. The username and password are passed to A"thenticatedWebSessionBs method sign2n("sername4 password and if authentication succeeds* the user is redirected to the original page with method contin"e/o+riginal:estination. The session class and the application class used in the proHect are reported here( "ession class(
public class .asic5uthentication)ession extends 5uthenticatedWeb)ession public .asic5uthentication)ession7*eEuest reEuest: super7reEuest:1 &

Wicket free user guide

171

1= 'ecurity with Wicket

!'4erride public boolean authenticate7)tring username, )tring passCord: //user is authenticated i% both username and passCord are eEual to ICicketerI return username.eEuals7passCord: UU username.eEuals79Cicketer9:1 & !'4erride public *oles get*oles7: return null1 & &

Application class(
public class Wicket5pplication extends 5uthenticatedWeb5pplication !'4erride public Class<Dome#age> getDome#age7: return Dome#age.class1 & !'4erride protected Class<? extends 5bstract5uthenticatedWeb)ession> getWeb)essionClass7: return .asic5uthentication)ession.class1 & !'4erride protected Class<? extends Web#age> get)ign$n#ageClass7: return )ign$n#age.class1 & &

The authentication logic inside a"thenticate has been #ept Euite tri.ial in order to ma#e the code as clean as possible. Please note also that session class must ha.e a constructor that accepts an instance of class )e6"est.

12.1.#

3edirecting user to an intermediate page

<ethod restart)esponseAtSign2nPage is an e,ample of redirecting user to an intermediate page before allowing him to access to the reEuested page. This method internally throws e,ception org.apache.wicket.)estart)esponseAt2nterceptPage'(ception which sa.es the &+: of the reEuested page into session metadata and then redirects user to the page passed as constructor parameter (the sign in page). ComponentBs method redirect/o2nterceptPage(Page wor#s in much the same way as restart)esponseAtSign2nPage but it allows us to specify which page to use as intermediate page(
redirectTo$ntercept#age7intermediate#age:1

>ote "ince both restart)esponseAtSign2nPage and redirect/o2ntercept Page internally throw an e,ception* the code placed after them will not be e,ecuted.

Wicket free user guide

174

1= 'ecurity with Wicket

12.2 Authori6ations
The authoriCation support pro.ided by 2ic#et is built around the concept of authori<ation strategy which is represented by interface 2A"thori3ationStrateg, (in pac#age org.apache.wicket .a"thori3ation)(
public inter%ace $5uthoriPation)trateg" //inter%ace methods <T extends $*eEuestableComponent> boolean is$nstantiation5uthoriPed7Class<T> componentClass:1 boolean is5ction5uthoriPed7Component component, 5ction action:1 //de%ault authoriPation strateg" that alloCs e4er"thing public static %inal $5uthoriPation)trateg" 5//'WM5// 8 neC $5uthoriPation)trateg"7: !'4erride public <T extends $*eEuestableComponent> boolean is$nstantiation5uthoriPed7%inal Class<T> c: return true1 & !'4erride public boolean is5ction5uthoriPed7Component c, 5ction action: return true1 & &1 &

This interface defines two methods( is2nstantiationA"thori3ed chec#s if user is allowed to instantiate a gi.en component. isActionA"thori3ed chec#s if user is authoriCed to perform a gi.en action on a componentBs instance. The standard actions chec#ed by this method are defined into class Action and are Action.'NA1L' and Action.)'N:'). -nside 2A"thori3ationStrateg, we can also find a default implementation of the interface (called 5//'WM5//) that allows e.eryone to instantiate e.ery component and perform e.ery possible action on it. This is the default strategy adopted by class Application. To change the authoriCation strategy in use we must register the desired implementation into security settings (interface 2Sec"rit,Settings) during initialiCation phase with method setA"thori3ation Strateg,(
//5pplication class code... !'4erride public 4oid init7: super.init7:1 get)ecurit")ettings7:.set5uthoriPation)trateg"7m"5uthoriPation)trateg":1 & //...

-f we want to combine the action of two or more authoriCation strategies we can chain them with
Wicket free user guide

17$

1= 'ecurity with Wicket

strategy Compo"ndA"thori3ationStrateg, which implements composite patter for authoriCation strategiesA5. <ost of the times we wonBt need to implement an 2A"thori3ationStrateg, from scratch as 2ic#et already comes with a set of built-in strategies. -n the ne,t paragraphs we will see some of these strategies that can be used to implement an effecti.e and fle,ible security policy.

12.2.1

8implePageAuthori6ation8trateg

Abstract class SimplePageA"thori3ationStrateg, (in pac#age org.apache.wicket. a"thori3ation.strategies.page) is a strategy that chec#s user authoriCations calling abstract method isA"thori3ed only for those pages that are subclasses of a gi.en supertype. -f isA"thori3ed returns %alse * the user is redirected to the sign in page specified as second constructor parameter(
)imple#age5uthoriPation)trateg" authoriPation)trateg" 8 neC )imple#age5uthoriPation)trateg"7 #ageClassToCheck.class, )ign$n#age.class: protected boolean is5uthoriPed7: //5uthentication code... & &1

By default SimplePageA"thori3ationStrateg, chec#s for permissions only on pages. -f we want to change this beha.ior and chec# also other #inds of components* we must o.erride method isActionA"thori3ed and implement our custom logic inside it.

12.2.2

3ole?=ased strategies

At the end of paragraph 17.1.1 we ha.e introduced AbstractA"thenticatedWebSessionBs method get)oles which is pro.ided to support role-based authoriCation returning the set of roles granted to the current user. -n 2ic#et roles are simple strings li#e FBA"-!O&"I+G or FAD<- G (they donBt need to be capitaliCed) and they are handled with class org.apache.wicket.a"throles.a"thori3ation.strategies. role.)oles. This class e,tends standard HashSet collection adding some functionalities to chec# whether the set contains one or more roles. !lass )oles already defines roles )oles.9S') and )oles.A:M2N. The session class in the following e,ample returns a custom F"-0 IDO- G role for e.ery authenticated user and it adds an )oles.A:M2N role if username is eEual to superuser(
class .asic5uthentication*oles)ession extends 5uthenticatedWeb)ession pri4ate )tring userName1 public .asic5uthentication*oles)ession7*eEuest reEuest: super7reEuest:1 & !'4erride public boolean authenticate7)tring username, )tring passCord: boolean auth*esult8 %alse1 auth*esult 8 //some authentication logic...
65 "n page 3> we have seen the same pattern implemented by Ae&uestCycle0istenerCollection for re&uest cycle listeners $

Wicket free user guide

173

1= 'ecurity with Wicket

i%7auth*esult: userName 8 username1 return auth*esult1 & !'4erride public *oles get*oles7: *oles result*oles 8 neC *oles7:1 i%7is)igned$n7:: result*oles.add79)$-N(+M$N9:1 i%7userName.eEuals79superuser9:: result*oles.add7*oles.5+;$N:1 return result*oles1 & &

+oles can be adopted to apply security restrictions on our pages and components. This can be done using one of the two built-in authoriCation strategies that e,tend super class Abstract)ole A"thori3ationStrateg,Wicket( Meta:ata)oleA"thori3ationStrateg, and Annotations )oleA"thori3ationStrateg, The difference between these two strategies is that Meta:ata)oleA"thori3ationStrateg, handles role-based authoriCations with 2ic#et metadata while Annotations)oleA"thori3ation@ Strateg, uses Ka.a annotations. >ote Application class A"thenticatedWebApplication already sets Meta:ata )oleA"thori3ationStrateg, and Annotations)oleA"thori3ation Strateg, as its own authoriCation strategies (it uses a compound strategy as we will see in paragraph 17.4.3). The code that we will see in the ne,t e,amples is for illustrati.e purpose only. -f our application class inherits from A"thenticatedWebApplication we wonBt need to configure anything to use these two strategies. 12.2.2.1 0sing roles with metadata "trategy Meta:ata)oleA"thori3ationStrateg, uses application and components metadata to implement role-based authoriCations. The class defines a set of static methods a"thori3e that can be used to specify which roles are allowed to instantiate a component and which roles can perform a gi.en action on a component. The following code snippet reports both application and session classes from proHect 4eta@ata"olesStrategy#0ample and illustrates how to use Meta:ata)oleA"thori3ationStrateg, to allow access to a gi.en page (Admin+nl,Page) only to AD<- role( Application class(
public class Wicket5pplication extends 5uthenticatedWeb5pplication !'4erride public Class<? extends Web#age> getDome#age7:

Wicket free user guide

175

1= 'ecurity with Wicket

return Dome#age.class1 & !'4erride protected Class<? extends 5bstract5uthenticatedWeb)ession> getWeb)essionClass7: return .asic5uthentication)ession.class1 & !'4erride protected Class<? extends Web#age> get)ign$n#ageClass7: return )ign$n#age.class1 & !'4erride public 4oid init7: get)ecurit")ettings7:.set5uthoriPation)trateg"7neC ;eta+ata*ole5uthoriPation)trateg" 7this::1 ;eta+ata*ole5uthoriPation)trateg".authoriPe75dmin'nl"#age.class, *oles.5+;$N:1 & &

"ession class(
public class .asic5uthentication)ession extends 5uthenticatedWeb)ession pri4ate )tring username1 public .asic5uthentication)ession7*eEuest reEuest: super7reEuest:1 & !'4erride public boolean authenticate7)tring username, )tring passCord: //user is authenticated i% username and passCord are eEual boolean auth*esult 8 username.eEuals7passCord:1 i%7auth*esult: this.username 8 username1 return auth*esult1 & public *oles get*oles7: *oles result*oles 8 neC *oles7:1 //i% user is signed in add the relati4e role i%7is)igned$n7:: result*oles.add79)$-N(+M$N9:1 //i% username is eEual to IsuperuserI add the 5+;$N role i%7usernameF8 null UU username.eEuals79superuser9:: result*oles.add7*oles.5+;$N:1 return result*oles1 & !'4erride

Wicket free user guide

17A

1= 'ecurity with Wicket

public 4oid sign'ut7: super.sign'ut7:1 username 8 null1 & &

The code that instantiates Meta:ata)oleA"thori3ationStrateg, and set it as applicationBs strategy is inside application class method init. Any subclass of Abstract)oleA"thori3ationStrateg,Wicket needs an implementation of interface 2)oleCheckingStrateg, to be instantiated. =or this purpose in the code abo.e we used the application class itself because its base class A"thenticatedWebApplication already implements interface 2)oleCheckingStrateg,. By default A"thenticatedWebApplication chec#s for authoriCations using the roles returned by the current AbstractA"thenticated WebSession. As final step inside init we grant the access to page Admin+nl,Page to AD<- role calling method a"thori3e. The code from session class has three interesting methods. The first is a"thenticate which considers as .alid credentials e.ery pair of username and password ha.ing the same .alue. The second notable method is get)oles which returns role "-0 IDO- if user is authenticated and it adds role AD<- if username is eEual to superuser. =inally* we ha.e method sign+"t which has been o.erridden in order to clean the username field used internally to generate roles. ow if we run the proHect and we try to access to Admin+nl,Page from the home page without ha.ing the AD<- role* we will be redirected to the default access-denied page used by 2ic#et(

The access-denied page can be customiCed using method setAccess:eniedPage(Class7D e(tends Page8 of setting interface 2ApplicationSettings(
//5pplication class code... !'4erride public 4oid init7: get5pplication)ettings7:.set5ccess+enied#age7;"Custom5ccess+enied#age.class:1 &

Kust li#e custom FPage e,piredG page (see chapter A.4.5)* also custom FAccess deniedG page must be boo#mar#able. 12.2.2.2 0sing roles with annotations "trategy Annotations)oleA"thori3ationStrateg, relies on two built-in annotations to handle role-based authoriCations. These annotations are A"thori3e2nstantiation and A"thori3e Action. As their names suggest the first annotation specifies which roles are allowed to instantiate the annotated component while the second must be used to indicate which roles are allowed to perform a specific action on the annotated component. -n the following e,ample we use annotations to ma#e a page accessible only to signed-in users and to enable it only if user has the AD<- role(
Wicket free user guide

176

1= 'ecurity with Wicket

!5uthoriPe$nstantiation79)$-N(+M$N9: !5uthoriPe5ction7action 8 9(N5./(9, roles 8 public class ;"#age extends Web#age //#age class code... & 95+;$N9&:

+emember that when a component is not enabled* user can render it but he can neither clic# on its lin#s nor interact with its forms. I,ample proHect $nnotations"olesStrategy#0ample is a re.isited .ersion of 4eta@ata"olesStrategy #0ample where we use Annotations)oleA"thori3ationStrateg, as authoriCation strategy. To ensure that page Admin+nl,Page is accessible only to AD<- role we ha.e used the following annotation(
!5uthoriPe$nstantiation795+;$N9: public class 5dmin'nl"#age extends Web#age //#age class code... &

12.2.3

.atching an unauthori6ed component instantiation

-nterface 29na"thori3edComponent2nstantiationListener (in pac#age org.apache. wicket.a"thori3ation) is pro.ided to gi.e the chance to handle the case in which a user tries to instantiate a component without ha.ing the permissions to do it. The method defined inside this interface is on9na"thori3ed2nstantiation(Component and it is e,ecuted whene.er a user attempts to e,ecute an unauthoriCed instantiation. This listener must be registered into applicationBs security settings with method set9na"thori3ed Component2nstantiationListener defined by setting interface 2Sec"rit,Settings. -n the following code snippet we register a listener that redirect user to a warning page if he tries to do a notallowed instantiation(
public class Wicket5pplication extends 5uthenticatedWeb5pplication //5pplication code... !'4erride public 4oid init7: get)ecurit")ettings7:.set0nauthoriPedComponent$nstantiation/istener7 neC $0nauthoriPedComponent$nstantiation/istener7: !'4erride public 4oid on0nauthoriPed$nstantiation7Component component: component.set*esponse#age75uthWarning#age.class:1 & &:1 & &

-n addition to interface 2)oleCheckingStrateg,* class A"thenticatedWebApplication implements also 29na"thori3edComponent2nstantiationListener and registers itself as listener for unauthoriCed instantiations. By default A"thenticatedWebApplication redirects users to sign-in page if they are not signed-in and they try to instantiate a restricted component. @therwise* if users are already signed in but they are

Wicket free user guide

177

1= 'ecurity with Wicket

not allowed to instantiate a gi.en component* an 9na"thori3ed2nstantiation'(ception will be thrown.

12.2.#

8trateg 3oleAuthori6ation8trateg

!lass )oleA"thori3ationStrateg, is a compound strategy that combines both Meta:ata )oleA"thori3ationStrateg, and Annotations)oleA"thori3ationStrateg,. This is the strategy used internally by A"thenticatedWebApplication.

12.3 0sing H**P8 protocol


9TTP" is the standard technology adopted on -nternet to create a secure communication channel between web applications and their users. -n 2ic#et we can easily protect our pages with 9TTP" mounting a special reEuest mapper called HttpsMapper and using annotation )e6"ireHttps with those pages we want to ser.e o.er this protocol. Both these two entities are in pac#age org.apache.wicket.protocol.https. HttpsMapper wraps an e,isting mapper and redirects incoming reEuests to 9TTP" if the related response must render a page containing annotation )e6"ireHttps. <ost of the times the wrapped mapper will be the root one* Hust li#e we saw before for Cr,ptoManager in paragraph 7.A.A. Another parameter needed to build a HttpsMapper is an instance of class HttpsCon0ig. This class allows us to specify which ports must be used for 9TTP" and 9TTP. By default the port numbers used by these two protocols are respecti.ely 33$ and 7%. The following code is ta#en from proHect HttpsProtocol#0ample and illustrates how to enable 9TTP" in our applications(
//5pplication class code... !'4erride public 4oid init7: set*oot*eEuest;apper7neC Dttps;apper7get*oot*eEuest;apper7:, neC DttpsCon%ig7BABA, <<R:::1 &

ow we can use annotation )e6"ireHttps to specify which pages must be ser.ed using 9TTP"(
!*eEuireDttps public class Dome#age extends Web#age public Dome#age7%inal #age#arameters parameters: super7parameters:1 & &

-f we want to protect many pages with 9TTP" without adding annotation )e6"ireHttps to each of them* we can annotate a mar#er interface or a base page class and implement/e,tend it in any page we want to ma#e secure( <ar#er interface(
!*eEuireDttps public inter%ace $;arker &

Base class(

Wicket free user guide

178

1= 'ecurity with Wicket

!*eEuireDttps public class .aseClass extends Web#age //#age code... &

"ecure page inheriting from .aseClass(


public class Dttps#age extends .aseClass //#age code... &

"ecure page implementing $;arker(


public class Dttps#age implements $;arker //#age code... &

12.# Package 3esource Guard


2ic#et internally uses an entity called package resource guard to protect pac#age resources from e,ternal access. This entity is an implementation of interface org.apache.wicket.mark"p.html. 2Package)eso"rce*"ard. By default 2ic#et applications use as pac#age resource guard class Sec"rePackage)eso"rce *"ard* which allows to access only to the following file e,tensions (grouped by type)( 7ava8cript files .ss files H*+, pages *extual files Hlash files Picture files Z.Hs Z.css Z.html Z.t,t Z.swf Z.png* Z.Hpg* Z.Hpeg* Z.gif* Z.ico* Z.cur* Z.bmp* Z.s.g

To modify the set of allowed files formats we can add one or more patterns with method addPattern (String . The rules to write a pattern are the following( patterns start with either a XNX or a X-X. -n the first case the pattern will add one or more file to the set while starting a pattern with a F-G we e,clude all the files matching the gi.en pattern. =or e,ample pattern F-web.,mlG e,cludes all web.,ml files in all directories. wildcard character FZG is supported as placeholder for Cero or more characters. =or e,ample pattern FNZ.mp3G adds all the mp3 files inside all directories. subdirectories are supported as well. =or e,ample pattern FNdocuments/Z.pdfG adds all pdf files under FdocumentsG directory. !haracter FZG can be used with directories to specify a nesting le.el. =or e,ample FNdocuments/Z/Z.pdfG adds all pdf files placed one le.el below FdocumentsG directory. a double wildcard character FZZG indicates Cero or more subdirectories. =or e,ample patter FNdocuments/ZZ/Z.pdfG adds all pdf files placed inside FdocumentsG directory or inside any of its subdirectories. Patterns that allow to access to e.ery file with a gi.en e,tensions (such as FNZ.pdfG) should be always a.oided in fa.our of more restricti.e e,pressions that contain a directory structure(

Wicket free user guide

18%

1= 'ecurity with Wicket

//5pplication class code... !'4erride public 4oid init7: $#ackage*esource-uard package*esource-uard 8 application.get*esource)ettings7: .get#ackage*esource-uard7:1 i% 7package*esource-uard instanceo% )ecure#ackage*esource-uard: )ecure#ackage*esource-uard guard 8 7)ecure#ackage*esource-uard: package*esource-uard1 //5lloC to access onl" to pd% %iles placed in the QpublicN director". guard.add#attern79>public/*.pd%9:1 & &

12.( 8ummar
-n this chapter we ha.e seen the components and the mechanisms that allow us to implement security policies in our 2ic#et-based applications. 2ic#et comes with an out of the bo, support for both authoriCation and authentication. The central element of authoriCation mechanism is the interface 2A"thori3ationStrateg, which decouples our components from any detail about security strategy. The implementations of this interface must decide if a user is allowed to instantiate a gi.en page or component and if she/he can perform a gi.en action on it. 2ic#et nati.ely supports role-based authoriCations with strategies Meta:ata)oleA"thori3ation Strateg, and Annotations)oleA"thori3ationStrateg,. The difference between these two strategies is that the first offers a programmatic approach for role handling while the second promotes a declarati.e approach using built-in annotations. After ha.ing e,plored how 2ic#et internally implements authentication and authoriCation* in the last part of the chapter we ha.e learnt how to configure our applications to support 9TTP" and how to specify which pages must be ser.ed o.er this protocol. -n the last paragraph we ha.e seen how 2ic#et protects pac#age resources with a guard entity that allows us to decide which pac#age resources can be accessed from users.

Wicket free user guide

181

1> Test .riven .evelopment with Wicket

1. $est 0riven 0evelopment with Wicket


Test Dri.en De.elopmentAA has become a crucial acti.ity for e.ery modern de.elopment methodology. This chapter will co.er the built-in support for testing pro.ided by 2ic#et with its rich set of helper and mock classes that allows us to test our components and our applications in isolation (i.e without the need for a ser.let container) using K&nit* the de facto standard for Ka.a unit testing. -n this chapter we will see how to write unit tests for our applications and components and we will learn how to use helper classes to simulate user na.igation and write acceptance tests without the need of any testing framewor# other than K&nit. The K&nit .ersion used in this chapter is 3.,.

14.1 0tilit class Wicket*ester


A good way to start getting confident with 2ic#et unit testing support is loo#ing at the test case class /estHomePage that is automatically generated by <a.en when we use 2ic#et archetype to create a new proHect(

9ere is the content of /estHomePage(


public class TestDome#age pri4ate WicketTester tester1 !.e%ore public 4oid set0p7: tester 8 neC WicketTester7neC Wicket5pplication7::1 & !Test public 4oid homepage*enders)uccess%ull"7: //start and render the test page tester.start#age7Dome#age.class:1 //assert rendered page class tester.assert*endered#age7Dome#age.class:1 & &

The central class in a 2ic#et testing is org.apache.wicket."til.tester.Wicket/ester. This


66 http: en.wikipedia.org wiki !est*driven1development

Wicket free user guide

184

1> Test .riven .evelopment with Wicket

utility class pro.ides a set of methods to render a component* clic# lin#s* chec# if page contains a gi.en component or a feedbac# message* and so on. The basic test case shipped with /estHomePage illustrates how Wicket/ester is typically instantiated (inside method set9p( ). -n order to test our components* Wicket/ester needs to use an instance of WebApplication. &sually* we will use our application class as WebApplication* but we can also decide to build Wicket/ester in.o#ing its no-argument constructor and letting it automatically build a moc# web application (an instance of class org.apache.wicket.mock. MockApplication). The code from /estHomePage introduces two basic methods to test our pages. The first is method startPage that renders a new instance of the gi.en page class and sets it as current rendered page for Wicket/ester. The second method is assert)enderedPage which chec#s if the current rendered page is an instance of the gi.en class. -n this way if /estHomePage succeeds we are sure that page HomePage has been rendered without any problem. The last rendered page can be retrie.ed with method getLast)enderedPage. ThatBs only a taste of what Wicket/ester can do. -n the ne,t paragraphs we will see how it can be used to test e.ery element that composes a 2ic#et page (lin#s* models* beha.iors* etc...).

14.1.1

*esting links

A clic# on a 2ic#et lin# can be simulated with method clickLink which ta#es in input the lin# component or the page-relati.e path to it. To see an e,ample of usage of clickLink* letBs consider again proHect %ife(ycleStages"evisited. As we #now from chapter 5 the home page of the proHect alternately displays two different labels (F=irst labelG and F"econd labelG)* swapping between them each time button 9reload9 is clic#ed. The code from its test case chec#s that label has actually changed after button 9reload9 has been pressed(
//... !Test public 4oid sCitch/abelTest7: //start and render the test page tester.start#age7Dome#age.class:1 //assert rendered page class tester.assert*endered#age7Dome#age.class:1 //assert rendered label tester.assert/abel79label9, 93irst label9:1 //simulate a click on 9reload9 button tester.click/ink79reload9:1 //assert rendered label tester.assert/abel79label9, 9)econd label9:1 & //...

-n the code abo.e we ha.e used clickLink to clic# on the 9reload9 button and force page to be rendered again. -n addition* we ha.e used also method assertLabel that chec#s if a gi.en label contains the e,pected te,t. By default clickLink assumes that AKAL is enabled on client side. To switch AKAL off we can use another .ersion of this method that ta#es in input the path to the lin# component and a boolean flag that indicates if AKAL must be enabled (tr"e) or not (0alse).
//... //simulate a click on a button Cithout 5L5] support tester.click/ink79reload9, %alse:1

Wicket free user guide

18$

1> Test .riven .evelopment with Wicket

//...

14.1.2

*esting component status

Wicket/ester pro.ides also a set of methods to test the states of a component. They are( assertDna=ledJ8tring path@Iassert5isa=ledJ8tring path@( they test if a component is enabled or not. assertEisi=leJ8tring path@Iassert!nvisi=leJ8tring path@( they test component .isibility. assert3e1uired(8tring path@( chec#s if a form component is reEuired. -n the test case from proHect (ustom@atepicker$-a0 we used assert'nabled<assert:isabled to chec# if button 9update9 really disables our datepic#er(
//... !Test public 4oid test+isable+ate#ickerWith.utton7: //start and render the test page tester.start#age7Dome#age.class:1 //assert that datepicker is enabled tester.assert(nabled79%orm:datepicker9:1 //click on update button to disable datepicker tester.click/ink79update9:1 //assert that datepicker is disabled tester.assert+isabled79%orm:datepicker9:1 & //...

14.1.3

*esting components in isolation

<ethod startComponent(Component can be used to test a component in isolation without ha.ing to create a container page for this purpose. The target component is rendered and both its methods on2nitiali3e( and on1e0ore)ender( are e,ecuted. -n the test case from proHect (ustom;orm(omponentPanel we used this method to chec# if our custom form component correctly renders its internal label(
//... !Test public 4oid testCustom#anelContains/abel7: Temperature+egree3ield %ield 8 neC Temperature+egree3ield79%ield9, ;odel.o%7A.AA::1 //0se standard L0nit class 5ssert 5ssert.assertNull7%ield.get79mesurament0nit9::1 tester.startComponent7%ield:1 5ssert.assertNotNull7%ield.get79mesurament0nit9::1 & //...

-f test reEuires a page we can use startComponent2nPage(Component generates a page for our component.

which automatically

14.1.#

*esting the response

Wicket/ester allows us to access to the last response generated during testing with method getLast)esponse. The returned .alue is an instance of class MockHttpSer!let)esponse that pro.ides helper methods to e,tract informations from moc#ed reEuest.

Wicket free user guide

183

1> Test .riven .evelopment with Wicket

-n the test case from proHect (ustom"esource4ounting we e,tract the te,t contained in the last response with method get:oc"ment and we chec# if it is eEual to the +"" feed used for the test(
//... !Test public 4oid test;ounted*esource*esponse7: throCs $'(xception, 3eed(xception tester.start*esource7neC *))#roducer*esource7::1 )tring responseTxt 8 tester.get/ast*esponse7:.get+ocument7:1 //Crite the *)) %eed used in the test into a ."te5rra"'utput)tream ."te5rra"'utput)tream output)tream 8 neC ."te5rra"'utput)tream7:1 Writer Criter 8 neC 'utput)treamWriter7output)tream:1 )"nd3eed'utput output 8 neC )"nd3eed'utput7:1 output.output7*))#roducer*esource.get3eed7:, Criter:1 //the response and the *)) must be eEual 5ssert.assert(Euals7responseTxt, output)tream.to)tring7::1 & //...

To simulate a reEuest to the custom resource we used method start)eso"rce which can be used also with resource references.

14.1.(

*esting 03,s

Wicket/ester can be pointed to an arbitrary &+: with method e(ec"te9rl(String "rl . This can be useful to test mounted pages* resources or reEuest mappers(
//... //the resource Cas mapped at I/%oo/barI tester.execute0rl79./%oo/bar9:1 //...

14.1.-

*esting A7A9 components

-f our application uses AKAL to refresh components mar#up* we can test if A5a()e6"est/arget contains a gi.en component with Wicket/esterBs method assertComponent+nA5a()esponse(
//... //test i% 52ax*eEuestTarget contains a component 7using its instance: tester.assertComponent'n52ax*esponse7amount/abel:1 //... //test i% 52ax*eEuestTarget contains a component 7using its path: tester.assertComponent'n52ax*esponse79pathTo/abel:label$d9:1

-tBs also possible to use method isComponent+nA5a()esponse(Component cmp component has been added to A5a()e6"est/arget(
//... //test i% 52ax*eEuestTarget does N'T contain amount/abel

to #now if a

assert3alse7tester.isComponent'n52ax*esponse7amount/abel::1 //...

14.1.'

*esting A7A9 events

Wicket free user guide

185

1> Test .riven .evelopment with Wicket

Beha.ior A5a('!ent1eha!ior and its subclasses can be tested simulating AKAL e.ents with Wicket/esterBs method e(ec"teA5a('!ent(Component cmp4 String e!ent . 9ere is the sample code from proHect !est$-a0#vents#0ample( 9ome page code:
public class Dome#age extends Web#age public static )tring $N$TMO5/0( 8 9$nitial 4alue91 public static )tring 'TD(*MO5/0( 8 9'ther 4alue91 public Dome#age7%inal #age#arameters parameters: super7parameters:1 /abel label1 add7label 8 neC /abel79label9, $N$TMO5/0(::1 label.add7neC 52ax(4ent.eha4ior79click9: !'4erride protected 4oid on(4ent752ax*eEuestTarget target: //change labelIs data ob2ect getComponent7:.set+e%ault;odel'b2ect7'TD(*MO5/0(:1 target.add7getComponent7::1 & &:.set'utput;arkup$d7true:1 //... & &

Test method(
!Test public 4oid test52ax.eha4ior7: //start and render the test page tester.start#age7Dome#age.class:1 //test i% label has the initial expected 4alue tester.assert/abel79label9, Dome#age.$N$TMO5/0(:1 //simulate an 5L5] 9click9 e4ent tester.execute52ax(4ent79label9, 9click9:1 //test i% label has changed as expected tester.assert/abel79label9, Dome#age.'TD(*MO5/0(:1 &

14.1.2

*esting A7A9 =ehaviors

To test a generic AKAL beha.ior we can simulate a reEuest to it using Wicket/esterBs method e(ec"te1eha!ior(AbstractA5a(1eha!ior beha!ior (
//... 52ax3ormComponent0pdating.eha4ior a2ax.eha4ior 8 neC 52ax3ormComponent0pdating.eha4ior 79change9: !'4erride protected 4oid on0pdate752ax*eEuestTarget target: //... & &1 component.add7a2ax.eha4ior:1

Wicket free user guide

18A

1> Test .riven .evelopment with Wicket

//... //execute 5L5] beha4ior, i.e. on0pdate Cill be in4oked tester.execute.eha4ior7a2ax.eha4ior::1 //...

14.1.4

0sing a custom servlet context

-n paragraph 1$.8 we ha.e seen how to configure our application to store resource files into a custom folder placed inside webapp root folder (see proHect (ustom;olderF4arkup#0ample). -n order to write testing code for applications that use this #ind of customiCation* we must tell Wicket/ester which folder to use as webapp root. This is necessary as under test en.ironment we donBt ha.e any web ser.er* hence itBs impossible for Wicket/ester to retrie.e this parameter from ser.let conte,t. 2ebapp root folder can be passed to Wicket/esterBs constructor as further parameter li#e we did in the test case of proHect (ustom;olderF4arkup#0ample(
public class TestDome#age pri4ate WicketTester tester1 !.e%ore public 4oid set0p7: //build the path to Cebapp root %older 3ile cur+irector" 8 neC 3ile7)"stem.get#ropert"79user.dir9::1 3ile CebContext+ir 8 neC 3ile7cur+irector", 9src/main/Cebapp9:1 tester 8 neC WicketTester7neC Wicket5pplication7:, CebContext+ir.get5bsolute#ath7::1 & //test methods... &

14.2 *esting Wicket forms


2ic#et pro.ides utility class Form/ester that is e,pressly designed to test 2ic#et forms. A new Form/ester is returned by Wicket/esterBs method newForm/ester(String4 boolean which ta#es in input the page-relati.e path of the form we want to test and a boolean flag indicating if its form components must be filled with a blan# string(
//... //create a neC %orm tester Cithout %illing its %orm components Cith a blank string 3ormTester %ormTester 8 tester.neC3ormTester79%orm9, %alse:1 //...

Form/ester can simulate form submission with method s"bmit which ta#es in input as optional parameter the submitting component to use instead of the default one(
//... //create a neC %orm tester Cithout %illing its %orm components Cith a blank string 3ormTester %ormTester 8 tester.neC3ormTester79%orm9, %alse:1 //submit %orm Cith de%ault submitter %ormTester.submit7:1 //... //submit %orm using inner component IbuttonI as alternate button

Wicket free user guide

186

1> Test .riven .evelopment with Wicket

%ormTester.submit79button9:1

-f we want to submit a form with an e,ternal lin# component we can use method s"bmitLink (String path4 boolean page)elati!e specifying the path to the lin#. -n the ne,t paragraphs we will see how to use Wicket/ester and Form/ester to interact with a form and with its children components.

14.2.1

8etting form components input

The purpose of a 9T<: form is to collect user input. Form/ester comes with the following set of methods that simulate input insertion into formBs fields( setEalueJ8tring pathG 8tring value@ ( inserts the gi.en te,tual .alue into the specified component. -t can be used with components /e(tField and /e(tArea. A .ersion of this method that accepts a component instance instead of its path is also a.ailable. setEalueJ8tring check=ox!dG =oolean value@ ( sets the .alue of a gi.en Check1o( component. setHileJ8tring form.omponent!dG Hile fileG 8tring content* pe@ ( sets a File obHect on a File9ploadField component. selectJ8tring form.omponent!dG int index@( selects an option among a list of possible options owned by a component. -t supports components that are subclasses of AbstractChoice along with )adio*ro"p and Check*ro"p. select+ultipleJ8tring form.omponent!dG intMN indexes@( selects all the options corresponding to the gi.en array of inde,es. -t can be used with multiple-choice components li#e Check*ro"p or ListM"ltipleChoice. set-al"e is used inside method insert9sernamePassword to set the username and password fields of the form used in proHect Stateless%ogin;orm(
protected 4oid insert0sername#assCord7)tring username, )tring passCord: //start and render the test page tester.start#age7Dome#age.class:1 3ormTester %ormTester 8 tester.neC3ormTester79%orm9:1 //set credentials %ormTester.setOalue79username9, username:1 %ormTester.setOalue79passCord9, passCord:1 //submit %orm %ormTester.submit7:1 &

14.2.2

*esting feed=ack messages

To chec# if a page contains one or more e,pected feedbac# messages we can use the following methods pro.ided by Wicket/ester( assertHeed=ackJ8tring pathG 8tring... messages@( asserts that a gi.en panel contains the specified messages assert!nfo+essagesJ8tring... expected!nfo+essages@( asserts that the e,pected info messages are rendered in the page. assertDrror+essagesJ8tring... expectedDrror+essages@( asserts that the e,pected error messages are rendered in the page. assert2n0oMessages and assert'rrorMessages are used in the test case from proHect Stateless%ogin;orm to chec# that form generates a feedbac# message in accordance with the login

Wicket free user guide

187

1> Test .riven .evelopment with Wicket

result(
!Test public 4oid test;essage3or)uccess%ul/ogin7: inser0sername#assCord79user9, 9user9:1 tester.assert$n%o;essages790sername and passCord are correctF9:1 & !Test public 4oid test;essage3or3ailed/ogin 7: inser0sername#assCord79CrongCredential9, 9CrongCredential9:1 tester.assert(rror;essages79Wrong username or passCord9:1 &

14.2.3

*esting models

!omponent model can be tested as well. 2ith method assertModel-al"e we can test if a specific component has the e,pected data obHect inside its model. This method has been used in the test case of proHect 4odel(haining#0ample to chec# if the form and the drop-down menu share the same data obHect(
!Test public 4oid test3orm)elect)ame;odel'b2ect7: #erson/ist+etails person/ist+etails 8 neC #erson/ist+etails7:1 +rop+oCnChoice drop+oCnChoice 8 7+rop+oCnChoice: person/ist+etails.get79persons9:1 /ist choices 8 drop+oCnChoice.getChoices7:1 //select the second option o% the drop-doCn menu drop+oCnChoice.set;odel'b2ect7choices.get7@::1 //start and render the test page tester.start#age7person/ist+etails:1 //assert that %orm has the same data ob2ect used b" drop-doCn menu tester.assert;odelOalue79%orm9, drop+oCnChoice.get;odel'b2ect7::1 &

14.3 *esting markup with *ag*ester


-f we need to test component mar#up at a more fine-grained le.el* we can use class /ag/ester from pac#age org.apache.wicket."til.tester. This test class allows to chec# if the generated mar#up contains one or more tags ha.ing a gi.en attribute with a gi.en .alue. /ag/ester can not be directly instantiated but it comes with three factory methods that return one or more /ag/ester matching the searching criteria. -n the following test case (from proHect !ag!ester#0ample) we retrie.e the first tag of the home page (a <span> tag) ha.ing attribute class eEual to m"Class( 9omePage mar#up(
<html xmlns:Cicket89http://Cicket.apache.org9> <head> <meta charset89ut%-B9 /> <title></title> </head> <bod"> <span class89m"Class9></span>

Wicket free user guide

188

1> Test .riven .evelopment with Wicket

<di4 class89m"Class9></di4> </bod"> </html>

Test method(
!Test public 4oid home#age;arkupTest7: //start and render the test page tester.start#age7Dome#age.class:1 //retrie4e responseIs markup )tring responseTxt 8 tester.get/ast*esponse7:.get+ocument7:1 TagTester tagTester 8 TagTester.createTag."5ttribute7responseTxt, 9class9, 9m"Class9:1 5ssert.assertNotNull7tagTester:1 5ssert.assert(Euals79span9, tagTester.getName7::1 /ist<TagTester> tagTester/ist 8 TagTester.createTags."5ttribute7responseTxt, 9class9, 9m"Class9, %alse:1 5ssert.assert(Euals7=, tagTester/ist.siPe7::1 &

The name of the tag found by /ag/ester can be retrie.ed with its method getName. <ethod create/ags1,Attrib"te returns all the tags that ha.e the gi.en .alue on the gi.en attribute. -n the code abo.e we ha.e used this method to test that our mar#up contains two tags ha.ing attribute class eEual to m"Class.

14.# 8ummar
2ith a component-oriented framewor# we can test our pages and components as we use to do with any other Ka.a entity. 2ic#et offers a complete support for writing testing code* offering built-in tools to test nearly all the elements that build up our applications (pages* containers* lin#s* beha.iors* etc...). The main entity discussed in this chapter has been class Wicket/ester which can be used to write unit tests and acceptance tests for our application* but we ha.e also seen how to test forms with Form/ester and how to inspect mar#up with /ag/ester. -n addition to learning how to use the utility classes pro.ided by 2ic#et for testing* we ha.e also e,perienced the inno.ati.e approach of 2ic#et to web testing that allows to test components in isolation without the need of running our tests with a web ser.er and depending only on K&nit as testing framewor#.

Wicket free user guide

4%%

1> Test .riven .evelopment with Wicket

Wicket free user guide

4%1

7ppendix 7% working with /aven

2ppendix 26 working with %aven


A.1 8witching Wicket to 5DP,CF+D>* mode
As pointed out in the note at page 8* 2ic#et can be started in two modes* DIDI:@P<I T and DIP:@'<I T. 2hen we are in DIDI:@P<I T mode 2ic#et warns us at application startup with the following message(
******************************************************************** *** W5*N$N-: Wicket is running in +(O(/'#;(NT mode. *** ^^^^^^^^^^^ *** +o N'T deplo" to "our li4e ser4er7s: Cithout changing this. *** *** ***

*** )ee 5pplicationXgetCon%igurationT"pe7: %or more in%ormation. *** ********************************************************************

As we can read 2ic#et itself discourages us from using DIDI:@P<I T mode into production en.ironment. The running mode of our application can be configured in three different ways. The first one is adding a filter parameter inside deployment descriptor web.,ml(
<%ilter> <%ilter-name>Cicket.;"5pp</%ilter-name> <%ilter-class>org.apache.Cicket.protocol.http.Wicket3ilter</%ilter-class> <init-param> <param-name>applicationClassName</param-name> <param-4alue>org.CicketTutorial.Wicket5pplication</param-4alue> </init-param> <init-param> <param-name>con%iguration</param-name> <param-4alue>deplo"ment</param-4alue> </init-param> </%ilter>

The additional parameter is written in bold. The same parameter can be also e,pressed as conte,t parameter(
<context-param> <param-name>con%iguration</param-name> <param-4alue>deplo"ment</param-4alue> </context-param>

The third way to set the running mode is using system property wicket.con0ig"ration. This parameter can be specified in the command line that starts up the ser.er(
2a4a -+Cicket.con%iguration8deplo"ment ...

+emember that system properties o.erwrite other settings* so they are ideal to ensure that on

Wicket free user guide

4%4

7ppendix 7% working with /aven

production machine the running mode will be always set to DIP:@'<I T.

A.2 .reating a Wicket pro<ect from scratch and importing it into our favourite !5D.
>ote -n order to follow the instructions of this paragraph you must ha.e <a.en installed on your system. The installation of <a.en is out of the scope of this guide but you can easily find an e,tensi.e documentation about it on -nternet. Another reEuirement is a good -nternet connection (a flat AD": is enough) because <a.en needs to connect to its central repository to download the reEuired dependencies.

A.2.1 Hrom +aven to our !5D


2ic#et proHect and its dependencies are managed using <a.enA6. This tool is .ery useful also when we want to create a new proHect based on 2ic#et from scratch. 2ith a couple of shell commands we can generate a new proHect properly configured and ready to be imported into our fa.ourite -DI. The main step to create such a proHect is to run the command which generates proHectBs structure and its artifacts. -f we are not familiar with <a.en or we simply donBt want to type this command by hand* we can use the utility form on 2ic#et site at http(//wic#et.apache.org/start/Euic#start.html(

llustration 1% Wicket &uickstart page 9ere we ha.e to specify the root pac#age of our proHect ( .roup"d)* the proHect name (/rti0act"d) and
67 http: maven.apache.org

Wicket free user guide

4%$

7ppendix 7% working with /aven

which .ersion of 2ic#et we want to use (1ersion). @nce we ha.e run the resulting command in the @" shell* we will ha.e a new folder with the same name of the proHect (i.e the $rtifactId). -nside this folder we can find a file called pom.0ml. This is the main file used by <a.en to manage our proHect. =or e,ample* using Forg.wic#etTutorialG as CroupId and F<yProHectG as $rtifactId* we would obtain the following artifacts(
.\;"#ro2ect _ _ \---src >---main _ _ _ _ _ _ _ _ _ _ _ _ _ _ \---test \---2a4a \---org \---CicketTutorial TestDome#age.2a4a >---2a4a _ _ _ _ _ _ >---resources _ _ \---Cebapp \---W(.-$N3 Ceb.xml log<2.properties \---org \---CicketTutorial Dome#age.html Dome#age.2a4a Wicket5pplication.2a4a pom.xml

Amongst other things* file pom.,ml contains a section delimited by tag <dependencies> which declares the dependencies of our proHect. By default the <a.en archetype will add the following 2ic#et modules as dependencies(
... <dependencies> <F-W$C6(T +(#(N+(NC$() --> <group$d>org.apache.Cicket</group$d> <arti%act$d>Cicket-core</arti%act$d> <4ersion>W Cicket.4ersion&</4ersion> </dependenc"> <dependenc"> <group$d>org.apache.Cicket</group$d> <arti%act$d>Cicket-ioc</arti%act$d> <4ersion>W Cicket.4ersion&</4ersion> </dependenc"> <F-- '#T$'N5/ +(#(N+(NCG <dependenc"> <group$d>org.apache.Cicket</group$d> <arti%act$d>Cicket-extensions</arti%act$d> <4ersion>W Cicket.4ersion&</4ersion> <dependenc">

Wicket free user guide

4%3

7ppendix 7% working with /aven

</dependenc"> --> ... </dependencies> ...

-f we need to use more 2ic#et modules or additional libraries* we can add the appropriate L<: fragmentsA7 here.

A.2.2 !mporting a +aven pro<ect into our !5D


<a.en proHects can be easily imported into the most popular Ka.a -DIs. 9owe.er* the procedure needed to do this differs from -DI to -DI. -n this paragraph we can find the instructions to import <a.en proHects into three of the most popular -DIs among Ka.a de.elopers ( etBeans* KetBrains -DIA and Iclipse. >et;eans "tarting from .ersion A.6* etBeans includes <a.en support* hence we can start it and directly open the folder containing our proHect(

!5DA -DIA comes with a <a.en importing functionality that can be started under F=ile/ ew ProHect/-mport from e,ternal model/<a.enG. Then* we Hust ha.e to select the pom.,ml file of our proHect(

68 7s described in 7ppendix B6 the ?/0 needed to include a dependency can be found at http: mvnrepository.com

Wicket free user guide

4%5

7ppendix 7% working with /aven

Dclipse -f our -DI is Iclipse the import procedure is a little more comple,. Before opening the new proHect we must generate the Iclipse proHect artifacts running the following command from proHect root(
m4n eclipse:eclipse

ow to import our proHect into Iclipse we must create a classpath .ariable called 4+1"#P2 that must point to your local <a.en repository. This can be done selecting F2indow/PreferencesG and searching for F!lasspath DariablesG. The folder containing our local <a.en repository is usually under our user folder and is called .m4 (for e,ample under &ni, system is /home/>my&ser ame?/.m4/repository)(

llustration *% 'etting /*DAHP" variable @nce we ha.e created the classpath .ariable we can go to F=ile/-mport.../I,isting ProHect into 2or#spaceG* select the directory of the proHect and press F=inishG(

llustration 1% mporting existing pro#ect into Hclipse without coping the original pro#ect into workspace 4see the note below5

Wicket free user guide

4%A

7ppendix 7% working with /aven

@nce the proHect has been imported into Iclipse* we are free to use our fa.ourite plug-ins to run it or debug it (li#e for e,ample run-Hetty-run( http(//code.google.com/p/run-Hetty-run/). >ote Please note the option F!opy proHects into wor#spaceG in the pre.ious illustration. -f we select it* the original proHect generated with <a.en wonBt be affected by the changes made inside Iclipse because we will wor# on a copy of it under the current wor#space. >ote -f we modify the pom.,ml file (for e,ample adding further dependencies) we must regenerate proHectBs artifacts and refresh the proHect (=5 #ey) to reflect changes into Iclipse.

A.2.3 8peeding up development with plugins.


ow that we ha.e our proHect loaded into our -DI we could start coding our components directly by hand. 9owe.er it would be a shame to not le.erage the free and good 2ic#et plugins a.ailable for our -DI. The following is a brief o.er.iew of the most widely used plugins for each of the three main -DIs considered so far. >et;eans etBeans offers 2ic#et support thought B etBeans Plugin for 2ic#etB hosted at http(//Ha.a.net/proHects/nbwic#etsupport/. This plugin is released under !DD:-1.% license. 'ou can find a nice introduction guide to this plugin at http(//netbeans.org/#b/docs/web/Euic#startwebapps-wic#et.html. !5DA =or KetBrain -DIA we can use 2ic#et=orge plugin* hosted at 0oogle !ode http(//code.google.com/ p/wic#etforge/. The plugin is released under A"= 4.% license. Dclipse 2ith Iclipse we can install one of the plugins that supports 2ic#et. As of the writing of this document* the most popular is probably Qwic#ie* a.ailable in the Iclipse <ar#etplace and hosted on 0oogle !ode at http(//code.google.com/p/Ewic#ie/. Q2ic#ie is released under A"= 4.% license.

Wicket free user guide

4%6

7ppendix 7% working with /aven

Wicket free user guide

4%7

7ppendix B% pro#ect Wicket'tuff

2ppendix 76 pro8ect Wicket4tuff


;.1 What is pro<ect Wicket8tuff"
2ic#et"tuff is an umbrella proHect that gathers different 2ic#et-related proHects de.eloped and maintained by the community. The proHect is hosted on 0it9ub at https(//github.com/wic#etstuff/core. I.ery module is structured as a parent <a.en proHect containing the actual proHect that implements the new functionality and an e,ample proHect that illustrates how to use it in our code. The resulting directory structure of each module is the following(
\<module name>-parent _ >---<module name> \---<module name>-examples

"o far we ha.e introduced only modules /ryo Seriali<er and 3ava## In-ect* but 2ic#et"tuff comes with many other modules that can be used in our applications A8. "ome of them come in handy to impro.e the user e,perience of our pages with comple, components or integrating some popular web ser.ices (li#e 0oogle <aps6%) and Ka.a"cript libraries (li#e Tiny<!I61). This appendi, pro.ides a Euic# o.er.iew of what 2ic#et"tuff offers to enhance the usability and the .isually-appealing of our pages. >ote I.ery 2ic#et"tuff module can be downloaded as KA+ archi.e at http(//m.nrepository.com. This site pro.ides also the L<: fragment needed to include it as a dependency into our pom.,ml file64.

;.2 +odule tin mce


<odule tin"mce offers integration with the namesa#e Ka.a"cript library that turns our FhumbleG te,tareas into a full-featured 9T<: 2'"-2'0 editor(

69 The full list of the available modules can be found at https: github.com wicketstuff core wiki 70 http: maps.google.com 71 http: www.tinymce.com 72 n addition to /aven also vy6 Grape6 Gradle 6Buildr and 'BT are supported

Wicket free user guide

4%8

7ppendix B% pro#ect Wicket'tuff

To FtinyfyG a te,tarea component we must use beha.ior /in,Mce1eha!ior(


Text5rea text5rea 8 neC Text5rea79text5rea9, neC ;odel799::1 text5rea.add7neC Tin";ce.eha4ior7::1

By default /in,Mce1eha!ior adds only a basic set of functionalities to our te,tarea(

To add more functionalities we must use class /in,MC'Settings to register additional Tiny<!I plugins and to customiCe the toolbars buttons. The following code is an e,cerpt from e,ample page F"llFeat"red/in,MC'Page(
Tin";C()ettings settings 8 neC Tin";C()ettings7Tin";C()ettings.Theme.ad4anced:1 //... // %irst toolbar //... settings.add7.utton.neCdocument, Tin";C()ettings.Toolbar.%irst, Tin";C()ettings.#osition.be%ore:1 settings.add7.utton.separator, Tin";C()ettings.Toolbar.%irst, Tin";C()ettings.#osition.be%ore:1 settings.add7.utton.%ontselect, Tin";C()ettings.Toolbar.%irst, Tin";C()ettings.#osition.a%ter:1 //... // other settings settings.setToolbar5lign7Tin";C()ettings.5lign.le%t:1 settings.setToolbar/ocation7Tin";C()ettings./ocation.top:1 settings.set)tatusbar/ocation7Tin";C()ettings./ocation.bottom:1 settings.set*esiPing7true:1 //... Text5rea text5rea 8 neC Text5rea79ta9, neC ;odel7T(]T::1 text5rea.add7neC Tin";ce.eha4ior7settings::1

=or more configuration e,amples see pages inside pac#age wicket.contrib.e(amples.tin,mce in the e,ample proHect of the module.

;.3 +odule wicketstu00-!map3


<odule Cicketstu%%-gmapR integrates 0oogle <aps6$ ser.ice with 2ic#et pro.iding component org.wicketst"00.gmap.*Map. -f we want to embed 0oogle <aps into one of our pages we Hust need to add component *Map inside the page. The following snippet is ta#en from e,ample page SimplePage(

73 http: maps.google.com

Wicket free user guide

41%

7ppendix B% pro#ect Wicket'tuff

<ar#up code(
... <bod"> <di4 Cicket:id89map9>;ap</di4> </bod"> ...

Ka.a code(
public class )imple#age extends Wicket(xample#age public )imple#age7: -;ap map 8 neC -;ap79map9:1 map.set)treetOieCControl(nabled7%alse:1 map.set)caleControl(nabled7true:1 map.set)crollWheel`oom(nabled7true:1 map.setCenter7neC -/at/ng7T=.<[Z<S, @R.==BT[R::1 add7map:1 & &

The component defines a number of setters to customiCe its beha.ior and appearance. <ore info can be found on wi#i page https(//github.com/wic#etstuff/core/wi#i/0map$.

;.# +odule wicketstu00-!oo!lec#arts


To integrate the 0oogle !hart63 tool into our pages we can use module Cicketstu%%-googlecharts. To display a chart we must combine the following entities( component Chart* interface 2Chart:ata and class ChartPro!ider* all inside pac#age org.wicketst"00.googlecharts. The following snippet is ta#en from e,ample page Home( <ar#up code(
... <h=>Dello World</h=> <img Cicket:id89helloWorld9/> ...

Ka.a code(
$Chart+ata data 8 neC 5bstractChart+ata7: public doubleHJHJ get+ata7: return neC doubleHJHJ & &1 Chart#ro4ider pro4ider 8 neC Chart#ro4ider7neC +imension7=TA, @AA:, ChartT"pe.#$(MR+, data:1 pro4ider.set#ie/abels7neC )tringHJ 9Dello9, 9World9 &:1 add7neC Chart79helloWorld9, pro4ider::1 R<, == & &1

Displayed chart(
74 https: developers.google.com chart

Wicket free user guide

411

7ppendix B% pro#ect Wicket'tuff

As we can see in the snippet abo.e* component Chart must be used with <img> tag while the input data returned by 2Chart:ata must be a two-dimensional array of double .alues.

;.( +odule wicketstu00-inmet#od-!rid


<odule Cicketstu%%-inmethod-grid implements a sophisticated grid-component with class com. inmethod.grid.datagrid.:ata*rid. Kust li#e pageable repeaters (seen in paragraph 11.3) :ata*rid pro.ides data pagination and uses interface 2:ataPro!ider as data source. -n addition the component is completely aHa,ified(

:ata*rid supports also editable cells and row selection(

The following snippet illustrate how to use :ata*rid https(//github.com/wic#etstuff/core/wi#i/-n<ethod0rid( <ar#up code(
...

and

is

ta#en

from

wi#i

page

Wicket free user guide

414

7ppendix B% pro#ect Wicket'tuff

<di4 Cicket:id89grid9>-rid</di4> ...

Ka.a code(
%inal /ist<#erson> person/ist 8 //load a list o% #ersons %inal /ist+ata#ro4ider list+ata#ro4ider 8 neC /ist+ata#ro4ider7person/ist:1 //de%ine gridIs columns /ist<$-ridColumn> cols 8 7/ist: 5rra"s.as/ist7 neC #ropert"Column7neC ;odel793irst Name9:, 9%irstName9:, neC #ropert"Column7neC ;odel79/ast Name9:, 9lastName9::1 +ata-rid grid 8 neC +e%ault+ata-rid79grid9, neC +ata#ro4ider5dapter7list+ata#ro4ider:, cols:1 add7grid:1

-n the code abo.e we ha.e used con.enience class :e0a"lt:ata*rid that is a subclass of :ata*rid and it already comes with a na.igation toolbar. The e,ample pages are under pac#age com.inmethod.grid.e(amples.pages in the e,ample proHect which is hosted at http(//www.wic#et-library.com/inmethod-grid/data-grid/simple.

Wicket free user guide

41$

7ppendix B% pro#ect Wicket'tuff

Wicket free user guide

413

7lphabetical ndex

2lpha9etical Index
A
AbstractAHa,TimerBeha.ior........................................1A6 Abstract!hec#Bo,<odel............................................1A3 Abstract+esource.......................................................1$% Abstract+esource ......................................................1$3 Abstract+oleAuthoriCation"trategy2ic#et..................175 AbstractTree...............................................................1A% Acceptance test..........................................................184 Access-denied page...................................................176 AKAL...........................................................................155 AKAL beha.iors..........................................................1A5 AKAL call listener........................................................1A8 global listeners......................................................16$ AHa,Button..................................................................15A AHa,!hec#Bo,............................................................156 AHa,Iditable!hoice:abel............................................156 AHa,Iditable:abel.......................................................156 AHa,Iditable<ulti:ine:abel........................................156 AHa,I.entBeha.ior.....................................................1AA AHa,=allbac#Button.....................................................156 AHa,=allbac#:in#.........................................................156 AHa,=orm!omponent&pdatingBeha.ior.....................1A6 AHa,=orm"ubmitBeha.ior...........................................1A6 AHa,:in#..............................................................155* 15A AHa,+eEuestAttributes................................................1A7 AHa,+eEuestTarget.............................................155* 185 AHa,"ubmit:in#...........................................................15A Annotations+oleAuthoriCation"trategy.......................176 Application............................................................3A* 137 Application"ettings.....................................................154 Attribute wic#et(id.........................................................11 Attribute<odifier...........................................................4A Authenticated2ebApplication.....................168* 17%* 177 Authenticated2eb"ession.........................................168 Authentication.............................................................168 authentication e,ample.........................................17% on!onfigure............................................................$A Auto!ompleteTe,t=ield..............................................157 Autolin# ............................................................................ boo#mar#able pages...............................................5A pac#age resources................................................1$4 !allbac# &+:s............................................................13A !aptcha-mage+esource.............................................1$% !hec#Bo,...........................................................1%4* 1A4 !hec#Bo,<ultiple!hoice............................................1%3 !hec#bo,<ultiple!hoice"elector...............................1%5 !hec#Bo,"elector......................................................1%5 !hec#ed=older...........................................................1A4 !hoice+enderer.....................................................65* 66 !lassPath+esource=inder..........................................1$6 !omponent...............................................6* A5* 135* 137 and <odel...............................................................A5 !omponent ot=oundI,ception...................................14 !ompoundAuthoriCation"trategy................................173 !ompoundProperty<odel.......................................A7* 6$ continueTo@riginalDestination...................................17% !on.erter:ocator..........................................................8% !rypto<apper...............................................................A$

D
Data grid.....................................................................414 DataDiew....................................................................11$ populate-tem.........................................................11$ DateTe,t=ield.............................................................131 Default-tem+euse"trategy.........................................11$ Default<apper!onte,t..................................................A4 Default<utableTree ode...........................................1A1 Deprecated tree components.....................................1A1 DropDown!hoice.........................................................63

I
I.ent-based component communication...................137 I,ternal:in#..................................................................57

=
=ile&pload=ield.............................................................8A =lash messages...........................................................76 =older.........................................................................1A4 =orm.............................................................................6% feedbac# messages................................................74 multipart content.....................................................8A processing...............................................................74 .alidation.................................................................74 =orm!omponent...........................................................6% =orm!omponentPanel.................................................87 =ormTester.................................................................186 select.....................................................................187 select<ultiple........................................................187 set=ile...................................................................187 setDalue................................................................187 submit...................................................................186 submit:in#.............................................................187

B
Beha.ior.................................................................4A* $7 Beha.iors....................................................................135 Boo#mar#able pages....................................................53 Boo#mar#ablePage:in#................................................5A Border...........................................................................$4 Broadcast...................................................................137 Built-in .alidators..........................................................73 Bundles loo#up algorithm...........................................144 order of tra.ersed bundles....................................145 Button...........................................................................8$

!
Wicket free user guide

415

7lphabetical ndex

0
0enerating 9T<: mar#up from code.........................154 getDefault<odel@bHect.................................................64 get<ar#up-d..................................................................46 getPage........................................................................$A getParent......................................................................$A 0oogle !hart..............................................................411 0oogle <aps..............................................................41% 0uice..........................................................................165 0uiceApplication.........................................................167 02T...............................................................................5

9
9eader contribution....................................................1$$ 9eader-tem.................................................................1$$ 9ibernate........................................................................1 9TTP"........................................................................178 9ttp"ession..................................................................5% 9ttps<apper...............................................................178

-AHa,!all:istener.........................................................1A7 -AHa,-ndicatorAware....................................................1A7 -Application"ettings......................................................33 -AuthoriCation"trategy................................................17$ -Auto!omplete+enderer.............................................157 -!haining<odel.............................................................65 -!hoice+ender..............................................................65 -!omponentAware9eader!ontributor........................161 -!omponent-nherited<odel..........................................A8 -!on.erter.....................................................................78 -!on.erter:ocator.........................................................78 -DataPro.ider..............................................................11$ -Detachable..................................................................67 -I.ent.........................................................................138 -I.ent"in#..................................................................137 -I.ent"ource..............................................................137 -=orm"ubmitter.......................................................6%* 84 -=orm"ubmitting!omponent.........................................84 -9eader!ontributor.............................................1$$* 135 -9eader+esponse.......................................................1$$ --nitialiCer....................................................................15% --tem+euse"trategy....................................................11$ -Ka.a"cript:ibrary"ettings..........................................13$ -mage..........................................................................1$1 -<apper!onte,t............................................................A1 -<ar#up+esource"treamPro.ider..............................154 -<odel...........................................................................A5 -nde,ed parameters......................................................55 -ndicatingAHa,Button...................................................1A7 -ndicatingAHa,=allbac#:in#.........................................1A7 -ndicatingAHa,:in#.......................................................1A7 -nitialiCer.....................................................................15% -nternationaliCation and <odels..................................14A in.alidate......................................................................54 in.alidate ow...............................................................54 -Pac#age+esource0uard...........................................18% -Pageable...................................................................11$ -+eEuest!ycle:istener.................................................37 -+eEuest!yclePro.ider.................................................3A -+eEuest9andler...........................................................36
Wicket free user guide

handler resol.ing algorithm.....................................36 -+eEuest:istener........................................................13A -+eEuest<apper...........................................................36 -+esource...................................................................1$% Attributes...............................................................1$% -+esource=inder.........................................................1$6 -+esource"ettings......................................145* 1$6* 1$7 get+esource=inders..............................................1$7 get"tring+esource:oaders...................................145 -+esource"tream:ocator............................................1$6 -+ole!hec#ing"trategy...............................................176 -"ecurity"ettings.........................................................177 isInabled......................................................................4A -"erialiCer......................................................................34 -"ession:istener...........................................................38 isPage"tateless............................................................3% isTemporary..................................................................51 -"tring+esource:oader...............................................145 isDisible........................................................................4A -tem.............................................................................114 -TreePro.ider..............................................................1A1 -&nauthoriCed!omponent-nstantiation:istener..........177 -Dalidatable...................................................................76 -DalidationIrror.............................................................76 -Dalidator......................................................................74

K
Ka.aBeans....................................................................A6 Ka.aII -nHect..............................................................4%8 Ka.aII -nHect .............................................................165 Ka.aII!omponent-nHector.........................................165 Ka.a"erialiCer...............................................................34 KBoss "eam...............................................................165 K<L............................................................................15% &sing K<L to control 2ic#et apps........................15% KQuery integration......................................................13% KQueryDate=ield.........................................................131 KQuery&- integration...................................................13% K"=.................................................................................5 KTree..........................................................................1A1 K&nit.......................................................................5* 184

M
Mryo proHect..................................................................34 Mryo serialiCer.......................................................34* 4%8

:
:abel...................................................................7* 11* A5 :in#.........................................................................14* 53 on!lic#....................................................................14 :istDataPro.ider.........................................................11$ :ist-tem.......................................................................111 :istDiew......................................................................111 populate-tem.........................................................111 set+euse-tems......................................................114 :oadableDetachable<odel...........................................67 :ocale.........................................................................116 :ocaliCation in 2ic#et.................................................116

41A

7lphabetical ndex

<
<ar#up file....................................................................11 <ar#up!ontainer....................................................11* 17 <a.en.............................................................7* 184* 4%$ importing proHects into Iclipse..............................4%A importing proHects into -DIA.................................4%5 importing proHects into etBeans..........................4%5 <etadata.......................................................................54 <etaDataMey................................................................54 <etaData+oleAuthoriCation"trategy..........................175 <oc#9ttp"er.let+esponse.........................................183 <odal2indow.............................................................157 Page!reator..........................................................158 2indow!losed!allbac#........................................1A% <odel............................................................................A5 model chaining........................................................65 model detaching......................................................67 model inheritance....................................................A7 using more than one model....................................7% <odel (class)................................................................AA <ounted<apper...........................................................A% mountPage...................................................................A% <ulti=ile&pload=ield.....................................................86 <D! pattern...................................................................3

Q
Query string parameters...............................................53

+
+edirecting user to an intermediate page...................174 +efreshingDiew..........................................................114 populate-tem.........................................................114 +epeaters...................................................................11% +epeatingDiew...........................................................11% +eEuest........................................................................3A +eEuest!ycle.......................................................3A* 137 hoo# methods.........................................................37 listeners...................................................................37 reEuest processing..................................................36 using a custom reEuest cycle..................................3A +eEuest:istener-nterface...........................................13A +eEuire9ttps...............................................................178 +esource management.................................................... custom resources..................................................1$3 mounting resources..............................................1$5 pac#age resources................................................1$% resource dependencies.........................................1$3 resource references..............................................1$% static .s dynamic resources..................................1$% +esourceBundle.........................................................116 +esource+eference....................................................1$% +esource+esponse....................................................1$5 2rite!allbac#........................................................1$5 +esource"tream:ocator.............................................1$6 +esponse.....................................................................3A +estart+esponseAt-nterceptPageI,ception..............174 restart+esponseAt"ign-nPage...................................17% +euse-f<odelsIEual"trategy.....................................11$ +oleAuthoriCation"trategy..........................................178 +oles..........................................................................173

amed parameters.......................................................53 estedTree.................................................................1A1

@
onBefore+ender...........................................................$A on-nitialiCe.....................................................................$A on<odel!hanged.........................................................A5 on"ubmit......................................................................6% @penIKB....................................................................165

P
Pac#age<apper...........................................................A1 Pac#age+esource+eference......................................1$1 Page mounting................................................................. optional placeholders..............................................A1 placeholders............................................................A% Page serialiCation...................................................3%* 34 Page .ersioning............................................................3% disabling .ersioning................................................34 PageParameters.....................................................33* 53 Page+eference.............................................................34 Paging a.igator.........................................................113 Palette........................................................................1%6 Panel............................................................................17 PasswordTe,t=ield.......................................................64 Path............................................................................1$6 PatternDate!on.ert....................................................13$ P@K@............................................................................A6 Property<odel..............................................................A7 Property+esol.er..........................................................A7

"
"ecurePac#age+esource0uard.................................18% "erialiCable...................................................................AA "ession.................................................................38* 137 accessing to http session obHect.............................5% discarding session data..........................................54 session listener.......................................................38 setDefault<odel@bHect.................................................64 setInabled....................................................................4A set<ar#up-d..................................................................46 set@utput<ar#up-d.......................................................46 set@utput<ar#upPlaceholderTag...............................1A5 set+enderBody@nly.....................................................$% set+esponsePage..................................................1$* 37 setDersioned.................................................................34 setDisible................................................................44* 4A "hared+esource+eference........................................1$A "implePageAuthoriCation"trategy..............................173 "ortableDataPro.ider.................................................11$ "pring.............................................................1* 165* 16A "pring!omponent-nHector...........................................16A "tateful pages...............................................................3% "tateless pages................................................3%* 33* 55 "tateless:in#................................................................58 "truts..............................................................................1

Wicket free user guide

416

7lphabetical ndex

"ubmit:in#..............................................................8$* 83 "wing..............................................................................6 "wing/A2T.....................................................................6 "witching 2ic#et to DIP:@'<I T mode.................4%4

T
TagTester...................................................................188 Test Dri.en De.elopment...........................................184 Testing with 2ic#et........................................................... setting form component input................................187 testing AKAL beha.iors.........................................18A testing AKAL components.....................................185 testing AKAL e.ents..............................................185 testing component status......................................183 testing components in isolation.............................183 testing feedbac# messages..................................187 testing lin#s ..........................................................18$ testing models.......................................................188 testing web response............................................183 testing 2ic#et forms..............................................186 Te,t=ield.......................................................................64 Tiny<!I.....................................................................4%8 Tree repeaters............................................................1A% Tree<odelPro.ider.....................................................1A1

&
&nit test......................................................................184 &pdating hidden components .ia AKAL.....................1A5 url=or and map&rl=or ..................................................37 &rlPathPagParametersIncoder...................................A4

D
Daadin............................................................................5

2
2ebApplication and testing.............................................. 2ebApplication.....................................................18$ 2ebApplicationPath...........................................1$6* 1$7 2eb<ar#up!ontainer.............................................46* 47 2ebPage..................................................................6* 11

2eb"ession.................................................................38 2ic#et forms.................................................................6% 2ic#et :in#s.................................................................14 2ic#et modules..............................................................6 2ic#et plugins............................................................4%6 for Iclipse.............................................................4%6 for -DIA................................................................4%6 for etBeans.........................................................4%6 Qwic#ie.................................................................4%6 2ic#et=orge..........................................................4%6 2ic#et tags....................................................................... >wic#et(body/?........................................................$4 >wic#et(border?......................................................$4 >wic#et(child?.........................................................4$ >wic#et(enclosure?.................................................$1 >wic#et(e,tend?......................................................4$ >wic#et(fragment?...................................................47 >wic#et(head?.........................................................48 >wic#et(id?................................................................A >wic#et(lin#?...................................................5A* 1$4 >wic#et(message?................................................141 >wic#et(panel?........................................................18 >wic#et(remo.e?.....................................................$% 2ic#et+untimeI,ception..............................................14 2ic#et"er.let................................................................11 2ic#et"tuff...................................................34* 165* 4%8 2ic#etTester...............................................................184 assert!omponent@nAHa,+esponse......................185 assertInabled.......................................................183 assertIrror<essages............................................187 assert=eedbac#....................................................187 assert-nfo<essages..............................................187 assert:abel...........................................................18$ assert<odelDalue.................................................188 assert+enderedPage............................................18$ assert+eEuired......................................................183 assertDisible..........................................................183 clic#:in#................................................................18$ e,ecuteAHa,I.ent.................................................18A e,ecute&rl.............................................................185 get:ast+enderedPage..........................................18$ get:ast+esponse..................................................183 is!omponent@nAHa,+esponse.............................185 new=ormTester.....................................................186 start!omponent....................................................183 start!omponent-nPage.........................................183 startPage...............................................................18$ start+esource........................................................185

Wicket free user guide

417

You might also like