Added: wicket/common/site/trunk/_site/guide/chapter9.html
URL: 
http://svn.apache.org/viewvc/wicket/common/site/trunk/_site/guide/chapter9.html?rev=1527613&view=auto
==============================================================================
--- wicket/common/site/trunk/_site/guide/chapter9.html (added)
+++ wicket/common/site/trunk/_site/guide/chapter9.html Mon Sep 30 15:41:38 2013
@@ -0,0 +1,374 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+                      
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>
+<html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en">
+<head>
+    <title>9 Wicket Links and URL generation 1.0.0.BUILD-SNAPSHOT</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+    <link rel="stylesheet" href="../css/main.css" type="text/css" 
media="screen, print" title="Style" charset="utf-8"/>
+    <link rel="stylesheet" href="../css/pdf.css" type="text/css" media="print" 
title="PDF" charset="utf-8"/>
+    <script type="text/javascript">
+function addJsClass() {
+    var classes = document.body.className.split(" ");
+    classes.push("js");
+    document.body.className = classes.join(" ");
+}
+    </script>
+</head>
+
+<body class="body" onload="addJsClass();">
+<div id="navigation">
+    <ul>
+        <li>
+            <div id="nav-summary" onmouseover="toggleNavSummary(false)" 
onmouseout="toggleNavSummary(true)">
+                <a href="../guide/index.html" class="button">Table of 
contents</a>
+
+                <div id="nav-summary-childs" style="display:none;">
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter1.html"><strong>1</strong><span>Introduction</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter2.html"><strong>2</strong><span>Why should I learn 
Wicket?</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter3.html"><strong>3</strong><span>Wicket says &ldquo;Hello 
world!&rdquo;</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter4.html"><strong>4</strong><span>Wicket as page layout 
manager</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter5.html"><strong>5</strong><span>Keeping control over 
HTML</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter6.html"><strong>6</strong><span>Components 
lifecycle</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter7.html"><strong>7</strong><span>Page versioning and 
caching</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter8.html"><strong>8</strong><span>Under the hood of the 
request processing</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter9.html"><strong>9</strong><span>Wicket Links and URL 
generation</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter10.html"><strong>10</strong><span>Wicket models and 
forms</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter11.html"><strong>11</strong><span>Wicket forms in 
detail</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter12.html"><strong>12</strong><span>Displaying multiple 
items with repeaters</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter13.html"><strong>13</strong><span>Internationalization 
with Wicket</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter14.html"><strong>14</strong><span>Resource management 
with Wicket</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter15.html"><strong>15</strong><span>An example of 
integration with JavaScript</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter16.html"><strong>16</strong><span>Wicket advanced 
topics</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter17.html"><strong>17</strong><span>Working with 
AJAX</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter18.html"><strong>18</strong><span>Integration with 
enterprise containers</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter19.html"><strong>19</strong><span>Security with 
Wicket</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter20.html"><strong>20</strong><span>Test Driven Development 
with Wicket</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter21.html"><strong>21</strong><span>Test Driven Development 
with Wicket and Spring</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter22.html"><strong>22</strong><span>Wicket Best 
Practices</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter23.html"><strong>23</strong><span>Working with Maven 
(Appendix)</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter24.html"><strong>24</strong><span>Project WicketStuff 
(Appendix)</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0"><a 
href="../guide/chapter25.html"><strong>25</strong><span>Lost In Redirection 
With Apache Wicket (Appendix)</span></a>
+                    </div>
+                    
+                </div>
+            </div>
+        </li>
+        <li class="separator selected">
+            <a id="ref-button" onclick="localToggle(); return false;" 
href="#">Quick Reference</a>
+        </li>
+    </ul>
+</div>
+<div id="header">
+    <div class="images clearfix">
+        
+        <span id="logo"><a href="/" target="_blank"><img height="80px" 
src="http://comsysto.github.io/wicket-userguide/img/apache-wicket.png"/></a></span>
+        
+        
+        <span id="sponsor"><a href="http://www.comsysto.com/"; 
target="_blank"><img height="60px" 
src="http://comsysto.github.io/wicket-userguide/img/comsysto-logo.png"/></a></span>
+        
+    </div>
+    <p>Free Online Guide for Apache Wicket framework</p>
+</div>
+
+
+<table id="colset" border="0" cellpadding="0" cellspacing="0">
+    <tr>
+        <td id="col1">
+            <div id="main" class="corner-all">
+
+                
+                    <div class="toc-item prev-left"><a 
href="../guide/chapter8.html">&lt;&lt; <strong>8</strong><span>Under the hood 
of the request processing</span></a></div>
+                
+
+                <span id='toggle-col1' class="toggle">(<a href="#" 
onclick="localToggle(); return false;">Quick Reference</a>)</span>
+
+                
+                    <div class="toc-item next-right"><a 
href="../guide/chapter10.html"><strong>10</strong><span>Wicket models and 
forms</span> >></a></div>
+                
+
+
+                <div class="project">
+                    <h1>9 Wicket Links and URL generation - Reference 
Documentation</h1>
+
+                    <p><strong>Authors:</strong> Andrea Del Bene, Carsten 
Hufe, Christian Kroemer, Daniel Bartl</p>
+
+                    <p><strong>Version:</strong> 1.0.0.BUILD-SNAPSHOT</p>
+
+                    
+                </div>
+
+                
+                <div id="table-of-content">
+                    <h2>Table of Contents</h2>
+                    
+                    <div class="toc-item" style="margin-left:0px"><a 
href="#chapter9_1"><strong>9.1</strong><span>PageParameters</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0px"><a 
href="#chapter9_2"><strong>9.2</strong><span>Bookmarkable links</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0px"><a 
href="#chapter9_3"><strong>9.3</strong><span>Automatically creating 
bookmarkable links with tag &lt;wicket:link&gt;</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0px"><a 
href="#chapter9_4"><strong>9.4</strong><span>External links</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0px"><a 
href="#chapter9_5"><strong>9.5</strong><span>Stateless links</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0px"><a 
href="#chapter9_6"><strong>9.6</strong><span>Generating structured and clear 
URLs</span></a>
+                    </div>
+                    
+                    <div class="toc-item" style="margin-left:0px"><a 
href="#chapter9_7"><strong>9.7</strong><span>Summary</span></a>
+                    </div>
+                    
+                </div>
+                
+
+                
+
+<h1 id="chapter9">9 Wicket Links and URL generation</h1>
+Up to now we used component Link to move from a page to another and we have 
seen that it is quiet similar to a “click” event handler (see paragraph 
2.4).<p class="paragraph"/>However this component alone is not enough to build 
all possible kinds of links we may need in our pages. Therefore, Wicket offers 
other link components suited for those tasks which can not be accomplished with 
a basic Link.<p class="paragraph"/>Besides learning new link components, in 
this chapter we will also see how to customize the page URL generated by Wicket 
using the encoding facility provided by the framework and the page parameters 
that can be passed to a target page.
+
+
+
+<h2 id="chapter9_1">9.1 PageParameters</h2>
+<p class="paragraph"/>A common practice in web development is to pass data to 
a page using query string parameters (like 
?paramName1=paramValu1&#38;paramName2=paramValue2...). Wicket offers a more 
flexible and object oriented way to do this with models (we will see them in 
the next chapter). However, even if we are using Wicket, we still need to use 
query string parameters to exchange data with other Internet-based services. 
Consider for example a classic confirmation page which is linked inside an 
email to let users confirm important actions like password changing or the 
subscription to a mailing list. This kind of page usually expects to receive a 
query string parameter containing the id of the action to confirm.<p 
class="paragraph"/>Query string parameters can also be referred to as named 
parameters. In Wicket they are handled with class 
org.apache.wicket.request.mapper.parameter.PageParameters. Since named 
parameters are basically name-value pairs, PageParameters works in much t
 he same way as Java Map providing two methods to create/modify a parameter 
(add(String name, Object value) and set(String name, Object value)),  one 
method to remove an existing parameter (remove(String name)) and one to 
retrieve the value of a given parameter (get(String name)) . Here is a snippet 
to illustrate the usage of PageParameters:<p class="paragraph"/><div 
class="code"><pre>PageParameters pageParameters = <span 
class="java&#45;keyword">new</span> PageParameters(); 
+//add a couple of parameters
+pageParameters.add(<span class="java&#45;quote">"name"</span>, <span 
class="java&#45;quote">"John"</span>);
+pageParameters.add(<span class="java&#45;quote">"age"</span>, 28);
+//retrieve the value of 'age' parameter
+pageParameters.get(<span class="java&#45;quote">"age"</span>);</pre></div><p 
class="paragraph"/>Now that we have seen how to work with page parameters, 
let's see how to use them with our pages.<p 
class="paragraph"/><h3>PageParameters and bookmarkable pages</h3><p 
class="paragraph"/>Base class Page comes with a constructor which takes as 
input a PageParameters instance. If we use this superclass constructor in our 
page, PageParameters will be used to build the page URL and it can be retrieved 
at a later time with the Page's getPageParameters() method.<p 
class="paragraph"/>In the following example taken from the 
PageParametersExample project we have a home page with a link to a second page 
that uses a version of setResponsePage method that takes as input also a 
PageParameters to build the target page (named PageWithParameters). The code 
for the link and for the target page is the following:<p 
class="paragraph"/>Link code:<p class="paragraph"/><div 
class="code"><pre>add(<span class="ja
 va&#45;keyword">new</span> Link(<span 
class="java&#45;quote">"pageWithIndexParam"</span>) &#123;<p 
class="paragraph"/> @Override
+       <span class="java&#45;keyword">public</span> void onClick() &#123;<p 
class="paragraph"/>                PageParameters pageParameters = <span 
class="java&#45;keyword">new</span> PageParameters();
+               pageParameters.add(<span class="java&#45;quote">"foo"</span>, 
<span class="java&#45;quote">"foo"</span>);
+               pageParameters.add(<span class="java&#45;quote">"bar"</span>, 
<span class="java&#45;quote">"bar"</span>);<p class="paragraph"/>         
setResponsePage(PageWithParameters.class, pageParameters);
+       &#125;<p class="paragraph"/>&#125;);</pre></div><p 
class="paragraph"/>Target page code:<p class="paragraph"/><div 
class="code"><pre><span class="java&#45;keyword">public</span> class 
PageWithParameters <span class="java&#45;keyword">extends</span> WebPage &#123;
+       //Override superclass constructor
+       <span class="java&#45;keyword">public</span> 
PageWithParameters(PageParameters parameters) &#123;
+               <span class="java&#45;keyword">super</span>(parameters);
+       &#125;
+ &#125;</pre></div><p class="paragraph"/>The code is quite straightforward and 
it’s more interesting to look at the URL generated for the target page:<p 
class="paragraph"/><div class="code"><pre>&#60;app 
root&#62;/PageParametersExample/wicket/bookmarkable/org.wicketTutorial.PageWithParameters?foo=foo&#38;bar=bar</pre></div><p
 class="paragraph"/>At first glance the URL above could seem a little weird, 
except for the last part which contains the two named parameters used to build 
the target page.<p class="paragraph"/>The reason for this “strange” URL is 
that, as we explained in paragraph 6.2.5, when a page is instantiated using a 
constructor with no argument or using a constructor that accepts only a 
PageParameters, Wicket will try to generate a static URL for it, with no 
session-relative informations. This kind of URL is called bookmarkable because 
it can be saved by the users as a bookmark and accessed at a later time.<p 
class="paragraph"/>A bookmarkable URL is compos
 ed by a fixed prefix (which by default is bookmarkable) and the qualified name 
of the page class (org.wicketTutorial.PageWithParameters in our example). 
Segment wicket is another fixed prefix added by default during URL generation. 
In paragraph 8.6.4 we will see how to customize fixed prefixes with a custom 
implementation of IMapperContext interface.<p class="paragraph"/><h3>Indexed 
parameters</h3><p class="paragraph"/>Besides named parameters, Wicket also 
supports indexed parameters. These kinds of parameters are rendered as URL 
segments placed before named parameters. Let's consider for example the 
following URL:<p class="paragraph"/><div class="code"><pre>&#60;application 
path&#62;/foo/bar?1&#38;baz=baz</pre></div><p class="paragraph"/>The URL above 
contains two indexed parameters (foo and bar) and a query string consisting of 
the page id and a named parameter (baz). Just like named parameters also 
indexed parameters are handled by the PageParameters class. The methods 
provided b
 y PageParameters for indexed parameters are set(int index, Object object) (to 
add/modify a parameter), remove(int index)(to remove a parameter) and get(int 
index) (to read a parameter).<p class="paragraph"/>As their name suggests, 
indexed parameters are identified by a numeric index and they are rendered 
following the order in which they have been added to the PageParameters. The 
following is an example of indexed parameters:<p class="paragraph"/><div 
class="code"><pre>PageParameters pageParameters = <span 
class="java&#45;keyword">new</span> PageParameters(); 
+//add a couple of parameters
+pageParameters.set(0, <span class="java&#45;quote">"foo"</span>);
+pageParameters.set(1, <span class="java&#45;quote">"bar"</span>);
+//retrieve the value of the second parameter (<span 
class="java&#45;quote">"bar"</span>)
+pageParameters.get(1);</pre></div><p class="paragraph"/>Project 
PageParametersExample comes also with a link to a page with both indexed 
parameters and a named parameter:<p class="paragraph"/><div 
class="code"><pre>add(<span class="java&#45;keyword">new</span> Link(<span 
class="java&#45;quote">"pageWithNamedIndexParam"</span>) &#123;<p 
class="paragraph"/>  @Override
+       <span class="java&#45;keyword">public</span> void onClick() &#123;<p 
class="paragraph"/>                PageParameters pageParameters = <span 
class="java&#45;keyword">new</span> PageParameters();
+               pageParameters.set(0, <span 
class="java&#45;quote">"foo"</span>);
+               pageParameters.set(1, <span 
class="java&#45;quote">"bar"</span>);
+               pageParameters.add(<span class="java&#45;quote">"baz"</span>, 
<span class="java&#45;quote">"baz"</span>);<p class="paragraph"/>         
setResponsePage(PageWithParameters.class, pageParameters);
+       &#125;<p class="paragraph"/>&#125;);</pre></div><p 
class="paragraph"/>The URL generated for the linked page (PageWithParameters) 
is the one seen at the beginning of the paragraph.
+
+
+<h2 id="chapter9_2">9.2 Bookmarkable links</h2>
+<p class="paragraph"/>A link to a bookmarkable page can be built with the link 
component org.apache.wicket.markup.html.link.BookmarkablePageLink:<p 
class="paragraph"/><div class="code"><pre>BookmarkablePageLink bpl=<span 
class="java&#45;keyword">new</span> 
BookmarkablePageLink(PageWithParameters.class, pageParameters);</pre></div><p 
class="paragraph"/>The specific purpose of this component is to provide an 
anchor to a bookmarkable page, hence we don't have to implement any abstract 
method like we do with Link component.
+
+
+<h2 id="chapter9_3">9.3 Automatically creating bookmarkable links with tag 
<wicket:link></h2>
+<p class="paragraph"/>Bookmarkable pages can be linked directly inside markup 
files without writing any Java code. Using &#60;wicket:link&#62; tag we ask 
Wicket to automatically add bookmarkable links for the anchors wrapped inside 
it. Here is an example of usage of &#60;wicket:link&#62; tag taken from the 
home page of the project BookmarkablePageAutoLink:<p class="paragraph"/><div 
class="code"><pre>&#60;!DOCTYPE html&#62;
+&#60;html xmlns:wicket=<span 
class="java&#45;quote">"http://wicket.apache.org";</span>&#62;
+       &#60;head&#62;
+               &#60;meta charset=<span 
class="java&#45;quote">"utf&#45;8"</span> /&#62;
+               &#60;title&#62;Apache Wicket Quickstart&#60;/title&#62;
+       &#60;/head&#62;
+       &#60;body&#62;          
+          &#60;div id=<span class="java&#45;quote">"bd"</span>&#62;
+             &#60;wicket:link&#62;
+                       &#60;a href=<span 
class="java&#45;quote">"HomePage.html"</span>&#62;HomePage&#60;/a&#62;&#60;br/&#62;
+                       &#60;a href=<span 
class="java&#45;quote">"anotherPackage/SubPackagePage.html"</span>&#62;SubPackagePage&#60;/a&#62;
     
+             &#60;/wicket:link&#62;
+          &#60;/div&#62;               
+       &#60;/body&#62;
+&#60;/html&#62;</pre></div><p class="paragraph"/>The key part of the markup 
above is the href attribute which must contain the package-relative path to a 
page. The home page is inside package org.wicketTutorial which in turns 
contains the sub package anotherPackage. This package hierarchy is reflected by 
the href attributes: in the first anchor we have a link to the home page itself 
while the second anchor points to page SubPackagePage which is placed into sub 
package anotherPackage. Absolute paths are supported as well and we can use 
them if we want to specify the full package of a given page. For example the 
link to SubPackagePage could have been written in the following (more verbose) 
way:<p class="paragraph"/><div class="code"><pre>&#60;a href=<span 
class="java&#45;quote">"/org/wicketTutorial/anotherPackage/SubPackagePage.html"</span>&#62;SubPackagePage&#60;/a&#62;</pre></div><p
 class="paragraph"/>If we take a look also at the markup of SubPackagePage we 
can see that it contains
  a link to the home page which uses the parent directory selector (relative 
path):<p class="paragraph"/><div class="code"><pre>&#60;!DOCTYPE html&#62;
+&#60;html xmlns:wicket=<span 
class="java&#45;quote">"http://wicket.apache.org";</span>&#62;
+       &#60;head&#62;
+               &#60;meta charset=<span 
class="java&#45;quote">"utf&#45;8"</span> /&#62;
+               &#60;title&#62;Apache Wicket Quickstart&#60;/title&#62;
+       &#60;/head&#62;
+       &#60;body&#62;          
+               &#60;div id=<span class="java&#45;quote">"bd"</span>&#62;
+                       &#60;wicket:link&#62;
+                               &#60;a href=<span 
class="java&#45;quote">"../HomePage.html"</span>&#62;HomePage&#60;/a&#62;&#60;br/&#62;
+                               &#60;a href=<span 
class="java&#45;quote">"SubPackagePage.html"</span>&#62;SubPackagePage&#60;/a&#62;
                    
+                       &#60;/wicket:link&#62;
+               &#60;/div&#62;          
+       &#60;/body&#62;
+&#60;/html&#62;</pre></div><p class="paragraph"/>Please note that any link to 
the current page (aka self link) is disabled. For example in the home page the 
self link is rendered like this:<p class="paragraph"/><div 
class="code"><pre>&#60;span&#62;&#60;em&#62;HomePage&#60;/em&#62;&#60;/span&#62;</pre></div><p
 class="paragraph"/>The markup used to render disabled links can be customized 
using the markup settings (interface IMarkupSettings) available in the 
application class:<p class="paragraph"/><div class="code"><pre>@Override
+<span class="java&#45;keyword">public</span> void init()
+&#123;
+       <span class="java&#45;keyword">super</span>.init();
+       //wrap disabled links with &#60;b&#62; tag
+       getMarkupSettings().setDefaultBeforeDisabledLink(<span 
class="java&#45;quote">"&#60;b&#62;"</span>);
+       getMarkupSettings().setDefaultAfterDisabledLink(<span 
class="java&#45;quote">"&#60;/b&#62;"</span>);            
+&#125;</pre></div><p class="paragraph"/>The purpose of &#60;wicket:link&#62; 
tag is not limited to just simplifying the usage of bookmarkable pages. As we 
we will see in chapter 13, this tag can also be adopted to manage web resources 
like pictures, CSS files, JavaScript files and so on.
+
+
+<h2 id="chapter9_4">9.4 External links</h2>
+<p class="paragraph"/>Since Wicket uses plain HTML markup files as templates, 
we can place an anchor to an external page directly inside the markup file. 
When we need to dynamically generate external anchors, we can use link 
component org.apache.wicket.markup.html.link.ExternalLink. In order to build an 
external link we must specify the value of the href attribute using a model or 
a plain string. In the next snippet, given an instance of Person, we generate a 
Google search query for its full name:<p class="paragraph"/>Html:<p 
class="paragraph"/><div class="code"><pre>&#60;a wicket:id=<span 
class="java&#45;quote">"externalSite"</span>&#62;Search me on 
Google!&#60;/a&#62;</pre></div><p class="paragraph"/>Java code:<p 
class="paragraph"/><div class="code"><pre>Person person = <span 
class="java&#45;keyword">new</span> Person(<span 
class="java&#45;quote">"John"</span>, <span 
class="java&#45;quote">"Smith"</span>); 
+<span class="java&#45;object">String</span> fullName = person.getFullName();
+//Space characters must be replaced by character '+'
+<span class="java&#45;object">String</span> googleQuery = <span 
class="java&#45;quote">"http://www.google.com/search?q=";</span> + 
fullName.replace(<span class="java&#45;quote">" "</span>, <span 
class="java&#45;quote">"+"</span>);
+add(<span class="java&#45;keyword">new</span> ExternalLink(<span 
class="java&#45;quote">"externalSite"</span>, googleQuery));</pre></div><p 
class="paragraph"/>Generated anchor:<p class="paragraph"/><div 
class="code"><pre>&#60;a href=<span 
class="java&#45;quote">"http://www.google.com/search?q=John+Smith";</span>&#62;Search
 me on Google!&#60;/a&#62;</pre></div><p class="paragraph"/>If we need to 
specify a dynamic value for the text inside the anchor, we can pass it as an 
additional constructor parameter:<p class="paragraph"/>Html:<p 
class="paragraph"/><div class="code"><pre>&#60;a wicket:id=<span 
class="java&#45;quote">"externalSite"</span>&#62;Label goes 
here...&#60;/a&#62;</pre></div><p class="paragraph"/>Java code:<p 
class="paragraph"/><div class="code"><pre>Person person = <span 
class="java&#45;keyword">new</span> Person(<span 
class="java&#45;quote">"John"</span>, <span 
class="java&#45;quote">"Smith"</span>); 
+<span class="java&#45;object">String</span> fullName = person.getFullName();
+<span class="java&#45;object">String</span> googleQuery = <span 
class="java&#45;quote">"http://www.google.com/search?q=";</span> + 
fullName.replace(<span class="java&#45;quote">" "</span>, <span 
class="java&#45;quote">"+"</span>);
+<span class="java&#45;object">String</span> linkLabel = <span 
class="java&#45;quote">"Search '"</span> + fullName + <span 
class="java&#45;quote">"' on Google."</span>;<p class="paragraph"/>add(<span 
class="java&#45;keyword">new</span> ExternalLink(<span 
class="java&#45;quote">"externalSite"</span>, googleQuery, 
linkLabel));</pre></div><p class="paragraph"/>Generated anchor:<p 
class="paragraph"/><div class="code"><pre>&#60;a href=<span 
class="java&#45;quote">"http://www.google.com/search?q=John+Smith";</span>&#62;Search
 'John Smith' on Google.&#60;/a&#62;</pre></div>
+
+
+<h2 id="chapter9_5">9.5 Stateless links</h2>
+<p class="paragraph"/>Component Link has a stateful nature, hence it cannot be 
used with stateless pages. To use links with these kinds of pages Wicket 
provides the convenience org.apache.wicket.markup.html. link.StatelessLink 
component which is basically a subtype of Link with the stateless hint set to 
true.<p class="paragraph"/>Please keep in mind that Wicket generates a new 
instance of a stateless page also to serve stateless links, so the code inside 
the onClick() method can not depend on instance variables. To illustrate this 
potential issue let's consider the following code (from the project 
StatelessPage) where the value of the variable index is used inside 
onclick():<p class="paragraph"/><div class="code"><pre><span 
class="java&#45;keyword">public</span> class StatelessPage <span 
class="java&#45;keyword">extends</span> WebPage &#123;
+       <span class="java&#45;keyword">private</span> <span 
class="java&#45;object">int</span> index = 0;<p class="paragraph"/> <span 
class="java&#45;keyword">public</span> StatelessPage(PageParameters parameters) 
&#123;
+               <span class="java&#45;keyword">super</span>(parameters);
+       &#125;<p class="paragraph"/>    @Override
+       <span class="java&#45;keyword">protected</span> void onInitialize() 
&#123;
+               <span class="java&#45;keyword">super</span>.onInitialize();
+               setStatelessHint(<span class="java&#45;keyword">true</span>);<p 
class="paragraph"/>             add(<span class="java&#45;keyword">new</span> 
StatelessLink(<span class="java&#45;quote">"statelessLink"</span>) &#123;<p 
class="paragraph"/>                   @Override
+                       <span class="java&#45;keyword">public</span> void 
onClick() &#123;
+                               //It will always print zero
+                               <span 
class="java&#45;object">System</span>.out.println(index++);
+                       &#125;<p class="paragraph"/>            &#125;);
+       &#125;  
+&#125;</pre></div><p class="paragraph"/>The printed value will always be zero 
because a new instance of the page is used every time the user clicks on the 
statelessLink link.
+
+
+<h2 id="chapter9_6">9.6 Generating structured and clear URLs</h2>
+<p class="paragraph"/>Having structured URLs in our site is a basic 
requirement if we want to build an efficient SEO1 strategy, but it also 
contributes to improve user experience with more intuitive URLs. Wicket 
provides two different ways to control URL generation. The first (and simplest) 
is to “mount” one or more pages to an arbitrary path, while a more powerful 
technique is to use custom implementations of IMapperContext and 
IPageParametersEncoder interfaces. In the next paragraphs we will learn both of 
these two techniques.<p class="paragraph"/><h3>Mounting a single page</h3><p 
class="paragraph"/>With Wicket we can mount a page to a given path in much the 
same way as we map a servlet filer to a desired path inside file web.xml (see 
page 9). Using mountPage(String path, Class &#60;T&#62; pageClass) method of 
the WepApplication class we tell Wicket to respond with a new instance of 
pageClass whenever a user navigates to the given path. In the application class 
of the
  project MountedPagesExample we mount MountedPage to the "/pageMount" path:<p 
class="paragraph"/><div class="code"><pre>@Override
+<span class="java&#45;keyword">public</span> void init()
+&#123;
+       <span class="java&#45;keyword">super</span>.init();
+       mountPage(<span class="java&#45;quote">"/pageMount"</span>, 
MountedPage.class);
+       //Other initialization code&#8230;
+&#125;</pre></div><p class="paragraph"/>The path provided to mountPage will be 
used to generate the URL for any page of the specified class:<p 
class="paragraph"/><div class="code"><pre>//it will <span 
class="java&#45;keyword">return</span> <span 
class="java&#45;quote">"/pageMount"</span>
+RequestCycle.get().urlFor(MountedPage.class);</pre></div><p 
class="paragraph"/>Under the hood the mountPage method mounts an instance of 
the request mapper org.apache. wicket.request.mapper.MountedMapper configured 
for the given path:<p class="paragraph"/><div class="code"><pre><span 
class="java&#45;keyword">public</span> <span 
class="java&#45;keyword">final</span> &#60;T <span 
class="java&#45;keyword">extends</span> Page&#62; void mountPage(<span 
class="java&#45;keyword">final</span> <span 
class="java&#45;object">String</span> path,<span 
class="java&#45;keyword">final</span> <span 
class="java&#45;object">Class</span>&#60;T&#62; pageClass) &#123;
+       mount(<span class="java&#45;keyword">new</span> MountedMapper(path, 
pageClass));
+&#125;</pre></div><p class="paragraph"/>Request mappers and the Application's 
method mount have been introduced in the previous chapter (paragraph 7.3.1).<p 
class="paragraph"/><h3>Using parameter placeholders with mounted pages</h3><p 
class="paragraph"/>The path specified for mounted pages can contain dynamic 
segments which are populated with the values of the named parameters used to 
build the page. These segments are declared using special segments called 
parameter placeholders. Consider the path used in the following example:<p 
class="paragraph"/><div class="code"><pre>mountPage(<span 
class="java&#45;quote">"/pageMount/$&#123;foo&#125;/otherSegm"</span>, 
MountedPageWithPlaceholder.class);</pre></div><p class="paragraph"/>The path 
used above is composed by three segments: the first and the last are fixed 
while the second will be replaced by the value of the named parameter foo that 
must be provided when the page  MountedPageWithPlaceholder is instantiated:<p 
class="paragraph"/>Jav
 a code:<p class="paragraph"/><div class="code"><pre>PageParameters 
pageParameters = <span class="java&#45;keyword">new</span> PageParameters();
+pageParameters.add(<span class="java&#45;quote">"foo"</span>, <span 
class="java&#45;quote">"foo"</span>);<p 
class="paragraph"/>setResponsePage(MountedPageWithPlaceholder.class, 
pageParameters)</pre></div><p class="paragraph"/>Generated URL:<p 
class="paragraph"/><div class="code"><pre>&#60;Application 
path&#62;/pageMount/foo/otherSegm</pre></div><p class="paragraph"/>On the 
contrary if we manually insert an URL like '&#60;web app 
path&#62;/pageMount/bar/otherSegm', we can read value 'bar' retrieving the 
named parameter foo inside our page.<p class="paragraph"/>Place holders can be 
declared as optional using the '#' character in place of '$':<p 
class="paragraph"/><div class="code"><pre>mountPage(<span 
class="java&#45;quote">"/pageMount/&#35;&#123;foo&#125;/otherSegm"</span>, 
MountedPageOptionalPlaceholder.class);</pre></div><p class="paragraph"/>If the 
named parameter for an optional placeholder is missing, the corresponding 
segment is removed from the final URL:<p class="paragraph"/>
 Java code:<p class="paragraph"/><div class="code"><pre>PageParameters 
pageParameters = <span class="java&#45;keyword">new</span> PageParameters();
+setResponsePage(MountedPageWithPlaceholder.class, 
pageParameters);</pre></div><p class="paragraph"/>Generated URL:<p 
class="paragraph"/><div class="code"><pre>&#60;Application 
path&#62;/pageMount/otherSegm</pre></div><p class="paragraph"/><h3>Mounting a 
package</h3><p class="paragraph"/>In addition to mounting a single page, Wicket 
allows to mount all of the pages inside a package to a given path. Method 
mountPackage(String path, Class&#60;T&#62; pageClass) of class WepApplication 
will mount every page inside pageClass's package to the specified path.<p 
class="paragraph"/>The resulting URL for package-mounted pages will have the 
following structure:<p class="paragraph"/><div 
class="code"><pre>&#60;Application 
path&#62;/mountedPath/&#60;PageClassName&#62;&#91;optional query 
string&#93;</pre></div><p class="paragraph"/>For example in the 
MountedPagesExample project we have mounted all pages inside the subpackage 
org.tutorialWicket.subPackage with this line of code:<p class="para
 graph"/><div class="code"><pre>mountPackage(<span 
class="java&#45;quote">"/mountPackage"</span>, 
StatefulPackageMount.class);</pre></div><p 
class="paragraph"/>StatefulPackageMount is one of the pages placed into the 
desired package and its URL will be:<p class="paragraph"/><div 
class="code"><pre>&#60;Application 
path&#62;/mountPackage/StatefulPackageMount?1</pre></div><p 
class="paragraph"/>Similarly to what is done by the mountPage method, the 
implementation of the mountPackage method mounts an instance of 
org.apache.wicket.request.mapper.PackageMapper to the given path.<p 
class="paragraph"/><h3>Providing custom mapper context to request 
mappers</h3><p class="paragraph"/>Interface 
org.apache.wicket.request.mapper.IMapperContext is used by request mappers to 
create new page instances and to retrieve static URL segments used to build and 
parse page URLs. Here is the list of these segments:
+<ul class="star">
+<li>Namespace: it's the first URL segment of non-mounted pages. By default its 
value is wicket.</li>
+<li>Identifier for non-bookmarkable URLs: it's the segment that identifies non 
bookmarkable pages. By default its value is page.</li>
+<li>Identifier for bookmarkable URLs: it's the segment that identifies 
bookmarkable pages. By default its value is bookmarkable (as we have seen 
before in paragraph 8.1.1).</li>
+<li>Identifier for resources: it's the segment that identifies Wicket 
resources. Its default value is resources. The topic of resource management 
will be covered in chapter 13.</li>
+</ul><p class="paragraph"/>IMapperContext provides a getter method for any 
segment listed above. By default Wicket uses class 
org.apache.wicket.DefaultMapperContext as mapper context.<p 
class="paragraph"/>Project CustomMapperContext is an example of customization 
of mapper context where we use index as identifier for non-bookmarkable pages 
and staticURL as identifier for bookmarkable pages. In this project, instead of 
implementing our mapper context from scratch, we used DefaultMapperContext as 
base class overriding just the two methods we need to achieve the desired 
result (getBookmarkableIdentifier() and getPageIdentifier()).  The final 
implementation is the following:<p class="paragraph"/><div 
class="code"><pre><span class="java&#45;keyword">public</span> class 
CustomMapperContext <span class="java&#45;keyword">extends</span> 
DefaultMapperContext&#123;<p class="paragraph"/>      @Override
+       <span class="java&#45;keyword">public</span> <span 
class="java&#45;object">String</span> getBookmarkableIdentifier() &#123;
+               <span class="java&#45;keyword">return</span> <span 
class="java&#45;quote">"staticURL"</span>;
+       &#125;<p class="paragraph"/>    @Override
+       <span class="java&#45;keyword">public</span> <span 
class="java&#45;object">String</span> getPageIdentifier() &#123;
+               <span class="java&#45;keyword">return</span> <span 
class="java&#45;quote">"index"</span>;
+       &#125;
+&#125;</pre></div><p class="paragraph"/>Now to use a custom mapper context in 
our application we must override the newMapperContext() method declared in the 
Application class and make it return our custom implementation of 
IMapperContext:<p class="paragraph"/><div class="code"><pre>@Override
+<span class="java&#45;keyword">protected</span> IMapperContext 
newMapperContext() &#123;
+       <span class="java&#45;keyword">return</span> <span 
class="java&#45;keyword">new</span> CustomMapperContext();
+&#125;</pre></div><p class="paragraph"/><h3>Controlling how page parameters 
are encoded with IPageParametersEncoder</h3><p class="paragraph"/>Some request 
mappers (like MountedMapper and PackageMapper) can delegate page parameters 
encoding/decoding to interface org.apache.wicket.request.mapper.parameter.IPage 
ParametersEncoder. This entity exposes two methods: encodePageParameters() and 
decodePageParameters(): the first  one is invoked to encode page parameters 
into an URL while the second one extracts parameters from the URL.<p 
class="paragraph"/>Wicket comes with a built-in implementation of this 
interface which encodes named page parameters as URL segments using the 
following patter: /paramName1/paramValue1/paramName2/param Value2...<p 
class="paragraph"/>This built-in encoder is 
org.apache.wicket.request.mapper.parameter.UrlPathPage ParametersEncoder class. 
In the PageParametersEncoderExample project we have manually mounted a  
MountedMapper that takes as input also an UrlPathPag
 eParametersEncoder:<p class="paragraph"/><div class="code"><pre>@Override
+<span class="java&#45;keyword">public</span> void init() &#123;
+       <span class="java&#45;keyword">super</span>.init();
+       mount(<span class="java&#45;keyword">new</span> MountedMapper(<span 
class="java&#45;quote">"/mountedPath"</span>, MountedPage.class, <span 
class="java&#45;keyword">new</span> UrlPathPageParametersEncoder()));
+&#125;</pre></div><p class="paragraph"/>The home page of the project contains 
just a link to the MountedPage web page. The code of the link and the resulting 
page URL are:<p class="paragraph"/>Link code:<p class="paragraph"/><div 
class="code"><pre>add(<span class="java&#45;keyword">new</span> Link(<span 
class="java&#45;quote">"mountedPage"</span>) &#123;<p class="paragraph"/>     
@Override
+       <span class="java&#45;keyword">public</span> void onClick() &#123;<p 
class="paragraph"/>                PageParameters pageParameters = <span 
class="java&#45;keyword">new</span> PageParameters();
+               pageParameters.add(<span class="java&#45;quote">"foo"</span>, 
<span class="java&#45;quote">"foo"</span>);
+               pageParameters.add(<span class="java&#45;quote">"bar"</span>, 
<span class="java&#45;quote">"bar"</span>);<p class="paragraph"/>         
setResponsePage(MountedPage.class, pageParameters);
+       &#125;
+&#125;);</pre></div><p class="paragraph"/>Generated URL:<p 
class="paragraph"/><div class="code"><pre>&#60;Application 
path&#62;/mountedPath/foo/foo/bar/bar?1</pre></div><p 
class="paragraph"/><h3>Encrypting page URLs</h3><p class="paragraph"/>Sometimes 
URLs are a double–edged sword for our site because they can expose too many 
details about the internal structure of our web application and malicious users 
could exploit them to perform a <a 
href="http://en.wikipedia.org/wiki/Cross-site_request_forgery"; 
target="blank">cross-site request forgery</a> .<p class="paragraph"/>To avoid 
this kind of security threat we can use the CryptoMapper request mapper which 
wraps an existing mapper and encrypts the original URL producing a single 
encrypted segment:<p class="paragraph"/><img border="0" class="center" 
src="../img/url-encrypted.png"></img><p class="paragraph"/>Typically, 
CryptoMapper is registered into a Wicket application as the root request mapper 
wrapping the default one:<p class="
 paragraph"/><div class="code"><pre>@Override
+<span class="java&#45;keyword">public</span> void init() &#123;
+       <span class="java&#45;keyword">super</span>.init();
+       setRootRequestMapper(<span class="java&#45;keyword">new</span> 
CryptoMapper(getRootRequestMapper(), <span 
class="java&#45;keyword">this</span>)); 
+       //pages and resources must be mounted after we have set CryptoMapper
+       mountPage(<span class="java&#45;quote">"/foo/"</span>, 
HomePage.class);</pre></div><p class="paragraph"/>As pointed out in the code 
above, pages and resources must be mounted after having set CryptoMapper as 
root mapper, otherwise the mounted paths will not work.
+
+
+<h2 id="chapter9_7">9.7 Summary</h2>
+<p class="paragraph"/>Links and URLs are not trivial topics as they may seem 
and in Wicket they are strictly interconnected. Developers must choose the 
right trade-off between producing structured URLs and avoiding to make them 
verbose and vulnerable.<p class="paragraph"/>In this chapter we have explored 
the tools provided by Wicket to control how URLs are generated. We have started 
with static URLs for bookmarkable pages and we have seen how to pass parameters 
to target pages with PageParameters. In the second part of the chapter we 
focused on mounting pages to a specific path and on controlling how parameters 
are encoded by Wicket. Finally, we have also seen how to encrypt URLs to 
prevent security vulnerabilities.
+
+
+                <div style="clear:both;margin-top:15px;"></div>
+                
+                    <div class="toc-item prev-left"><a 
href="../guide/chapter8.html">&lt;&lt; <strong>8</strong><span>Under the hood 
of the request processing</span></a></div>
+                
+                    <div class="toc-item next-right"><a 
href="../guide/chapter10.html"><strong>10</strong><span>Wicket models and 
forms</span> >></a></div>
+                
+                <div style="clear:both"></div>
+            </div>
+        </td>
+        <td id="col2">
+            <div class="local clearfix">
+                <div class="local-title">
+                    <a href="../guide/index.html" target="mainFrame">Quick 
Reference</a>
+                    <span class="toggle">(<a href="#" onclick="localToggle(); 
return false;">hide</a>)</span>
+                </div>
+                <div class="menu">
+                    
+                </div>
+            </div>
+        </td>
+    </tr>
+</table>
+
+<div id="footer">
+    
+Copyright &copy; 2013 — <a href="http://www.comsysto.com"; 
target="_blank">comSysto GmbH</a>
+<script>
+  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new 
Date();a=s.createElement(o),
+  
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+  ga('create', 'UA-43124634-1', 'comsysto.com');
+  ga('send', 'pageview');
+
+</script>
+
+    
+</div>
+
+<script type="text/javascript" src="../js/docs.js"></script>
+
+</body>
+</html>


Reply via email to