Modified: wicket/common/site/trunk/_site/guide/guide/requestProcessing.html URL: http://svn.apache.org/viewvc/wicket/common/site/trunk/_site/guide/guide/requestProcessing.html?rev=1562075&r1=1562074&r2=1562075&view=diff ============================================================================== --- wicket/common/site/trunk/_site/guide/guide/requestProcessing.html (original) +++ wicket/common/site/trunk/_site/guide/guide/requestProcessing.html Tue Jan 28 14:13:34 2014 @@ -51,55 +51,55 @@ function addJsClass() { <div class="toc-item" style="margin-left:0"><a href="../guide/requestProcessing.html"><strong>9</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>10</strong><span>Wicket Links and URL generation</span></a> + <div class="toc-item" style="margin-left:0"><a href="../guide/urls.html"><strong>10</strong><span>Wicket Links and URL generation</span></a> </div> - <div class="toc-item" style="margin-left:0"><a href="../guide/chapter10.html"><strong>11</strong><span>Wicket models and forms</span></a> + <div class="toc-item" style="margin-left:0"><a href="../guide/modelsforms.html"><strong>11</strong><span>Wicket models and forms</span></a> </div> - <div class="toc-item" style="margin-left:0"><a href="../guide/chapter11.html"><strong>12</strong><span>Wicket forms in detail</span></a> + <div class="toc-item" style="margin-left:0"><a href="../guide/forms2.html"><strong>12</strong><span>Wicket forms in detail</span></a> </div> - <div class="toc-item" style="margin-left:0"><a href="../guide/chapter12.html"><strong>13</strong><span>Displaying multiple items with repeaters</span></a> + <div class="toc-item" style="margin-left:0"><a href="../guide/repeaters.html"><strong>13</strong><span>Displaying multiple items with repeaters</span></a> </div> - <div class="toc-item" style="margin-left:0"><a href="../guide/chapter13.html"><strong>14</strong><span>Internationalization with Wicket</span></a> + <div class="toc-item" style="margin-left:0"><a href="../guide/i18n.html"><strong>14</strong><span>Internationalization with Wicket</span></a> </div> - <div class="toc-item" style="margin-left:0"><a href="../guide/chapter14.html"><strong>15</strong><span>Resource management with Wicket</span></a> + <div class="toc-item" style="margin-left:0"><a href="../guide/resources.html"><strong>15</strong><span>Resource management with Wicket</span></a> </div> - <div class="toc-item" style="margin-left:0"><a href="../guide/chapter15.html"><strong>16</strong><span>An example of integration with JavaScript</span></a> + <div class="toc-item" style="margin-left:0"><a href="../guide/jsintegration.html"><strong>16</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>17</strong><span>Wicket advanced topics</span></a> + <div class="toc-item" style="margin-left:0"><a href="../guide/advanced.html"><strong>17</strong><span>Wicket advanced topics</span></a> </div> - <div class="toc-item" style="margin-left:0"><a href="../guide/chapter17.html"><strong>18</strong><span>Working with AJAX</span></a> + <div class="toc-item" style="margin-left:0"><a href="../guide/ajax.html"><strong>18</strong><span>Working with AJAX</span></a> </div> - <div class="toc-item" style="margin-left:0"><a href="../guide/chapter18.html"><strong>19</strong><span>Integration with enterprise containers</span></a> + <div class="toc-item" style="margin-left:0"><a href="../guide/jee.html"><strong>19</strong><span>Integration with enterprise containers</span></a> </div> - <div class="toc-item" style="margin-left:0"><a href="../guide/chapter19.html"><strong>20</strong><span>Security with Wicket</span></a> + <div class="toc-item" style="margin-left:0"><a href="../guide/security.html"><strong>20</strong><span>Security with Wicket</span></a> </div> - <div class="toc-item" style="margin-left:0"><a href="../guide/chapter20.html"><strong>21</strong><span>Test Driven Development with Wicket</span></a> + <div class="toc-item" style="margin-left:0"><a href="../guide/testing.html"><strong>21</strong><span>Test Driven Development with Wicket</span></a> </div> - <div class="toc-item" style="margin-left:0"><a href="../guide/chapter21.html"><strong>22</strong><span>Test Driven Development with Wicket and Spring</span></a> + <div class="toc-item" style="margin-left:0"><a href="../guide/testingspring.html"><strong>22</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>23</strong><span>Wicket Best Practices</span></a> + <div class="toc-item" style="margin-left:0"><a href="../guide/bestpractices.html"><strong>23</strong><span>Wicket Best Practices</span></a> </div> - <div class="toc-item" style="margin-left:0"><a href="../guide/chapter23.html"><strong>24</strong><span>Working with Maven (Appendix)</span></a> + <div class="toc-item" style="margin-left:0"><a href="../guide/maven.html"><strong>24</strong><span>Working with Maven (Appendix)</span></a> </div> - <div class="toc-item" style="margin-left:0"><a href="../guide/chapter24.html"><strong>25</strong><span>Project WicketStuff (Appendix)</span></a> + <div class="toc-item" style="margin-left:0"><a href="../guide/wicketstuff.html"><strong>25</strong><span>Project WicketStuff (Appendix)</span></a> </div> - <div class="toc-item" style="margin-left:0"><a href="../guide/chapter25.html"><strong>26</strong><span>Lost In Redirection With Apache Wicket (Appendix)</span></a> + <div class="toc-item" style="margin-left:0"><a href="../guide/redirects.html"><strong>26</strong><span>Lost In Redirection With Apache Wicket (Appendix)</span></a> </div> <div class="toc-item" style="margin-left:0"><a href="../guide/contributing.html"><strong>27</strong><span>Contributing to this guide (Appendix)</span></a> @@ -138,7 +138,7 @@ function addJsClass() { <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/chapter9.html"><strong>10</strong><span>Wicket Links and URL generation</span> >></a></div> + <div class="toc-item next-right"><a href="../guide/urls.html"><strong>10</strong><span>Wicket Links and URL generation</span> >></a></div> @@ -284,7 +284,7 @@ Remember that invalidateNow() will immed <div class="toc-item prev-left"><a href="../guide/versioningCaching.html"><< <strong>8</strong><span>Page versioning and caching</span></a></div> - <div class="toc-item next-right"><a href="../guide/chapter9.html"><strong>10</strong><span>Wicket Links and URL generation</span> >></a></div> + <div class="toc-item next-right"><a href="../guide/urls.html"><strong>10</strong><span>Wicket Links and URL generation</span> >></a></div> <div style="clear:both"></div> </div>
Added: wicket/common/site/trunk/_site/guide/guide/resources.html URL: http://svn.apache.org/viewvc/wicket/common/site/trunk/_site/guide/guide/resources.html?rev=1562075&view=auto ============================================================================== --- wicket/common/site/trunk/_site/guide/guide/resources.html (added) +++ wicket/common/site/trunk/_site/guide/guide/resources.html Tue Jan 28 14:13:34 2014 @@ -0,0 +1,403 @@ +<!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>15 Resource management with Wicket 6.x</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/introduction.html"><strong>1</strong><span>Introduction</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/howToSource.html"><strong>2</strong><span>How to use the example code</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/whyLearn.html"><strong>3</strong><span>Why should I learn Wicket?</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/helloWorld.html"><strong>4</strong><span>Wicket says “Hello world!”</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/layout.html"><strong>5</strong><span>Wicket as page layout manager</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/keepControl.html"><strong>6</strong><span>Keeping control over HTML</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/componentLifecycle.html"><strong>7</strong><span>Components lifecycle</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/versioningCaching.html"><strong>8</strong><span>Page versioning and caching</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/requestProcessing.html"><strong>9</strong><span>Under the hood of the request processing</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/urls.html"><strong>10</strong><span>Wicket Links and URL generation</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/modelsforms.html"><strong>11</strong><span>Wicket models and forms</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/forms2.html"><strong>12</strong><span>Wicket forms in detail</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/repeaters.html"><strong>13</strong><span>Displaying multiple items with repeaters</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/i18n.html"><strong>14</strong><span>Internationalization with Wicket</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/resources.html"><strong>15</strong><span>Resource management with Wicket</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/jsintegration.html"><strong>16</strong><span>An example of integration with JavaScript</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/advanced.html"><strong>17</strong><span>Wicket advanced topics</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/ajax.html"><strong>18</strong><span>Working with AJAX</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/jee.html"><strong>19</strong><span>Integration with enterprise containers</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/security.html"><strong>20</strong><span>Security with Wicket</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/testing.html"><strong>21</strong><span>Test Driven Development with Wicket</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/testingspring.html"><strong>22</strong><span>Test Driven Development with Wicket and Spring</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/bestpractices.html"><strong>23</strong><span>Wicket Best Practices</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/maven.html"><strong>24</strong><span>Working with Maven (Appendix)</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/wicketstuff.html"><strong>25</strong><span>Project WicketStuff (Appendix)</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/redirects.html"><strong>26</strong><span>Lost In Redirection With Apache Wicket (Appendix)</span></a> + </div> + + <div class="toc-item" style="margin-left:0"><a href="../guide/contributing.html"><strong>27</strong><span>Contributing to this guide (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://wicket.apache.org/guide/img/apache-wicket.png"/></a></span> + + + <span id="sponsor"><a href="http://www.apache.org/" target="_blank"><img height="60px" src="http://wicket.apache.org/guide/img/asf_logo.gif"/></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/i18n.html"><< <strong>14</strong><span>Internationalization with Wicket</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/jsintegration.html"><strong>16</strong><span>An example of integration with JavaScript</span> >></a></div> + + + + <div class="project"> + <h1>15 Resource management with Wicket - Reference Documentation</h1> + + <p><strong>Authors:</strong> Andrea Del Bene, Carsten Hufe, Christian Kroemer, Daniel Bartl, Paul BorÈ</p> + + <p><strong>Version:</strong> 6.x</p> + + + </div> + + + <div id="table-of-content"> + <h2>Table of Contents</h2> + + <div class="toc-item" style="margin-left:0px"><a href="#resources_1"><strong>15.1</strong><span>Static vs dynamic resources</span></a> + </div> + + <div class="toc-item" style="margin-left:0px"><a href="#resources_2"><strong>15.2</strong><span>Resource references</span></a> + </div> + + <div class="toc-item" style="margin-left:0px"><a href="#resources_3"><strong>15.3</strong><span>Package resources</span></a> + </div> + + <div class="toc-item" style="margin-left:0px"><a href="#resources_4"><strong>15.4</strong><span>Adding resources to page header section</span></a> + </div> + + <div class="toc-item" style="margin-left:0px"><a href="#resources_5"><strong>15.5</strong><span>Resource dependencies</span></a> + </div> + + <div class="toc-item" style="margin-left:0px"><a href="#resources_6"><strong>15.6</strong><span>Aggregate multiple risources with resource bundles</span></a> + </div> + + <div class="toc-item" style="margin-left:0px"><a href="#resources_7"><strong>15.7</strong><span>Custom resources</span></a> + </div> + + <div class="toc-item" style="margin-left:0px"><a href="#resources_8"><strong>15.8</strong><span>Mounting resources</span></a> + </div> + + <div class="toc-item" style="margin-left:0px"><a href="#resources_9"><strong>15.9</strong><span>Shared resources</span></a> + </div> + + <div class="toc-item" style="margin-left:0px"><a href="#resources_10"><strong>15.10</strong><span>Customizing resource loading</span></a> + </div> + + <div class="toc-item" style="margin-left:0px"><a href="#resources_11"><strong>15.11</strong><span>Summary</span></a> + </div> + + </div> + + + + +<h1 id="resources">15 Resource management with Wicket</h1> +One of the biggest challenge for a web framework is to offer an efficient and consistent mechanism to handle internal resources such as CSS/JavaScript files, picture files, pdf and so on. Resources can be static (like an icon used across the site) or dynamic (they can be generated on the fly) and they can be made available to users as a download or as a simple URL.<p class="paragraph"/>In paragraph 4.6 we have already seen how to add CSS and JavaScript contents to the header section of the page. In the first half of this chapter we will learn a more sophisticated technique that allows us to manage static resources directly from code and âpackâ them with our custom components.<p class="paragraph"/>Then, in the second part of the chapter we will see how to implement custom resources to enrich our web application with more complex and dynamic functionalities. + + +<h2 id="resources_1">15.1 Static vs dynamic resources</h2> +<p class="paragraph"/>In Wicket a resource is an entity that can interact with the current request and response and It must implement interface <code>org.apache.wicket.request.resource.IResource</code>. This interface defines just method respond(IResource.Attributes attributes) where the nested class IResource. Attributes provides access to request, response and page parameters objects.<p class="paragraph"/>Resources can be static or dynamic. Static resources don't entail any computational effort to be generated and they generally correspond to a resource on the filesystem. On the contrary dynamic resources are generated on the fly when they are requested, following a specific logic coded inside them.<p class="paragraph"/>An example of dynamic resource is the built-in class CaptchaImageResource in package <code>org.apache.wicket.extensions.markup.html.captcha</code> which generates a captcha image each time is rendered.<p class="paragraph"/>As we will see in paragraph 13.6, develope rs can build custom resources extending base class <code>org.apache.wicket.request.resource.AbstractResource</code>. + + +<h2 id="resources_2">15.2 Resource references</h2> +<p class="paragraph"/>Most of the times in Wicket we won't directly instantiate a resource but rather we will use a reference to it. Resource references are represented by abstract class <code>org.apache.wicket.request.resource.ResourceReference</code> which returns a concrete resource with factory method getResource(). In this way we can lazy-initialize resources loading them only the first time they are requested. + + +<h2 id="resources_3">15.3 Package resources</h2> +<p class="paragraph"/>With HTML we use to include static resources in our pages using tags like <script>, <link> or <img>. This is what we have done so far writing our custom panels and pages. However, when we work with a component-oriented framework like Wicket, this classic approach becomes inadequate because it makes custom components hardly reusable. This happens when a component depends on a big number of resources. In such a case, if somebody wanted to use our custom component in his application, he would be forced to know which resources it depends on and make them available.<p class="paragraph"/>To solve this problem Wicket allows us to place static resource files into component package (like we do with markup and properties files) and load them from component code.<p class="paragraph"/>These kinds of resources are called package resources (a CSS and a JavaScript file in this screenshot):<p class="paragraph"/><img border="0" class="center" src="../img /package-resources.png"></img><p class="paragraph"/>With package resources custom components become independent and self-contained and client code can use them without worrying about their dependencies.<p class="paragraph"/>To load package resources Wicket provides class <code>org.apache.wicket.request.resource.PackageResourceReference</code>.<p class="paragraph"/>To identify a package resource we need to specify a class inside the target package and the name of the desired resource (most of the times this will be a file name).<p class="paragraph"/>In the following example taken from project ImageAsPackageRes, CustomPanel loads a picture file available as package resource and it displays it in a <img> tag using the built-in component <code>org.apache.wicket.markup.html.image.Image</code>:<p class="paragraph"/><strong class="bold">HTML:</strong> +<div class="code"><pre><html> +<head>...</head> +<body> +<wicket:panel> + Package resource image: <img wicket:id=<span class="java-quote">"packageResPicture"</span>/> +</wicket:panel> +</body> +</html></pre></div><p class="paragraph"/><strong class="bold">Jave Code:</strong> +<div class="code"><pre><span class="java-keyword">public</span> class CustomPanel <span class="java-keyword">extends</span> Panel {<p class="paragraph"/> <span class="java-keyword">public</span> CustomPanel(<span class="java-object">String</span> id) { + <span class="java-keyword">super</span>(id); + PackageResourceReference resourceReference = + <span class="java-keyword">new</span> PackageResourceReference(getClass(), <span class="java-quote">"calendar.jpg"</span>); + add(<span class="java-keyword">new</span> Image(<span class="java-quote">"packageResPicture"</span>, resourceReference)); + } +}</pre></div><p class="paragraph"/>Wicket will take care of generating a valid URL for file calendar.jpg. URLs for package resources have the following structure:<p class="paragraph"/><code><path to application root>/wicket/resource/<fully qualified classname>/<resource file name>-<ver-<id>>(.file extension)</code><p class="paragraph"/>In our example the URL for our picture file calendar.jpg is the following:<p class="paragraph"/><code>./wicket/resource/org.wicketTutorial.CustomPanel/calendar-ver-1297887542000.jpg</code><p class="paragraph"/>The first part of the URL is the relative path to the application root. In our example our page is already at the application's root so we have only a single-dotted segment. The next two segments, wicket and resource, are respectively the namespace and the identifier for resources seen in paragraph 8.6.4.<p class="paragraph"/>The fourth segment is the fully qualified name of the class used to locate t he resource and it is the scope of the package resource. In the last segment of the URL we can find the name of the resource (the file name).<p class="paragraph"/>As you can see Wicket has automatically appended to the file name a version identifier (ver-1297887542000). When Wicket runs in DEVELOPMENT mode this identifier contains the timestamp in millisecond indicating the last time the resource file was modified. This can be useful when we are developing our application and resource files are frequently modified. Appending the timestamp to the original name we are sure that our browser will use always the last version of the file and not an old, out of date, cached version.<p class="paragraph"/>When instead Wicket is running in DEPLOYMENT mode, the version identifier will contain the MD5 digest of the file instead of the timestamp. The digest is computed only the first time the resource is requested. This perfectly makes sense as static resources don't change so often when our app lication runs into production environment and when this appends the application is redeployed.<p class="paragraph"/><blockquote class="note"> +Package resources can be localized following the same rules seen for resource bundles and markup files:<p class="paragraph"/><img border="0" class="center" src="../img/package-resource-localization.png"></img><p class="paragraph"/>In the example illustrated in the picture above, if we try to retrieve package resource calendar.jpg when the current locale is set to French, the actual file returned will be calendar_fr.jpg. +</blockquote><p class="paragraph"/> +<h3>Using package resources with tag <wicket:link></h3><p class="paragraph"/>In paragraph 8.3 we have used tag <wicket:link> to automatically create links to bookmarkable pages. The same technique can be used also for package resources in order to use them directly from markup file. Let's assume for example that we have a picture file called icon.png placed in the same package of the current page. Under these conditions we can display the picture file using the following markup fragment:<p class="paragraph"/><div class="code"><pre><wicket:link> + <img src=<span class="java-quote">"icon.png"</span>/> +</wicket:link></pre></div><p class="paragraph"/>In the example above Wicket will populate the attribute src with the URL corresponding to the package resource icon.png. <wicket:link> supports also tag <link> for CSS files and tag <script> for JavaScript files. + + + +<h2 id="resources_4">15.4 Adding resources to page header section</h2> +<p class="paragraph"/>Wicket comes with interface <code>org.apache.wicket.markup.html.IHeaderContributor</code> which allows components and behaviors (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 <code>renderHead(IHeaderResponse response)</code> where <code>IHeaderResponse</code> is an interface which defines method <code>render(HeaderItem item)</code> to write static resources or free-form text into the header section of the page.<p class="paragraph"/>Header entries are instances of abstract class <code>org.apache.wicket.markup.head.HeaderItem</code>. Wicket provides a set of built-in implementations of this class suited for the most common types of resources. With the exception of <code>PriorityHeaderItem</code>, every implementation of <code>HeaderItem</code> is an abstract factory class: +<ul class="star"> +<li><strong class="bold">CssHeaderItem:</strong> represents a CSS resource. Factory methods provided by this class are <code>forReference</code> which takes in input a resource reference, <code>forUrl</code> which creates an CSS item from a given URL and <code>forCSS</code> which takes in input an arbitrary CSS string and an optional id value to identify the resource.</li> +<li><strong class="bold">JavaScriptHeaderItem:</strong> represents a JavaScript resource. Just like <code>CssHeaderItem</code> it provides factory methods <code>forReference</code> and <code>forUrl</code> along with method <code>forScript</code> which takes in input an arbitrary string representing the script and an optional id value to identify the resource. Method <code>forReference</code> also supports boolean parameter <code>defer</code> which renders the namesake attribute in the script tag (<code>defer</code> attribute indicates that our script must be execute only after the page has loaded).</li> +<li><strong class="bold">OnDomReadyHeaderItem:</strong> it adds JavaScript code that will be executed after the DOM has been built, but before external files (such as picture, CSS, etc...) have been loaded. The class provides a factory method <code>forScript</code> which takes in input an arbitrary string representing the script to execute.</li> +<li><strong class="bold">OnEventHeaderItem:</strong> the JavaScript code added with this class is executed when a specific JavaScript event is triggered on a given DOM element. The factory method is <code>forScript(String target, String event, CharSequence javaScript)</code>, where target is the id of a DOM element (or the element itself), event is the event that must trigger our code and javaScript is the code to execute.</li> +<li><strong class="bold">OnLoadHeaderItem:</strong> the JavaScript code added with this class is executed after the whole page is loaded, external files included. The factory method is <code>forScript(CharSequence javaScript)</code>.</li> +<li><strong class="bold">PriorityHeaderItem:</strong> it wraps another header item and ensures that it will have the priority over the other items during rendering phase.</li> +<li><strong class="bold">StringHeaderItem:</strong> with this class we can add an arbitrary text to the header section. Factory method is <code>forString(CharSequence string)</code>.</li> +</ul><p class="paragraph"/>In the following example our custom component loads a CSS file as a package resource (placed in the same package) and it adds it to header section.<p class="paragraph"/><div class="code"><pre><span class="java-keyword">public</span> class MyComponent <span class="java-keyword">extends</span> Component{<p class="paragraph"/> @Override + <span class="java-keyword">public</span> void renderHead(IHeaderResponse response) { + PackageResourceReference cssFile = + <span class="java-keyword">new</span> PackageResourceReference(<span class="java-keyword">this</span>.getClass(), <span class="java-quote">"style.css"</span>); + CssHeaderItem cssItem = CssHeaderItem.forReference(cssFile);<p class="paragraph"/> response.render(cssItem); + } +}</pre></div> + + + +<h2 id="resources_5">15.5 Resource dependencies</h2> +<p class="paragraph"/>Class <code>ResourceReference</code> allows to specify the resources it depends on overriding method <code>getDependencies()</code>. The method returns an iterator over the set of <code>HeaderItems</code> that must be rendered before the resource referenced by <code>ResourceReference</code> can be used. This can be really helpful when our resources are JavaScript or CSS libraries that in turn depend on other libraries.<p class="paragraph"/>For example we can use this method to ensure that a custom reference to JQueryUI library will find JQuery already loaded in the page:<p class="paragraph"/><div class="code"><pre>Url jqueyuiUrl = Url.parse(<span class="java-quote">"https://ajax.googleapis.com/ajax/libs/jqueryui/"</span> + + <span class="java-quote">"1.10.2/jquery-ui.min.js"</span>);<p class="paragraph"/>UrlResourceReference jqueryuiRef = <span class="java-keyword">new</span> UrlResourceReference(jqueyuiUrl){ + @Override + <span class="java-keyword">public</span> Iterable<? <span class="java-keyword">extends</span> HeaderItem> getDependencies() { + Application application = Application.get(); + ResourceReference jqueryRef = application.getJavaScriptLibrarySettings(). + getJQueryReference();<p class="paragraph"/> <span class="java-keyword">return</span> Arrays.asList(JavaScriptHeaderItem.forReference(jqueryRef)); + } +};</pre></div><p class="paragraph"/>Please note that in the code above we have built a resource reference using a URL to the desired library instead of a package resource holding the physical file.<p class="paragraph"/>The same method <code>getDependencies()</code> is defined also for class <code>HeaderItem</code>. + + +<h2 id="resources_6">15.6 Aggregate multiple risources with resource bundles</h2> +One of the best practices to make our web application faster and reduce its latency is to reduce the number of requests to the server to load page resources like JavaScript or CSS files. To achieve this goal some JavaScript-based build tools (like Grunt) allow to merge multiple files used in a page into a single file that can be loaded in a single request. Wicket provides class <code>org.apache.wicket.ResourceBundles</code> to aggregate multiple resource references into a single one. A resource bundle can be declared during application initialization listing all the resources that compose it:<p class="paragraph"/><div class="code"><pre>@Override +<span class="java-keyword">public</span> void init() { + <span class="java-keyword">super</span>.init();<p class="paragraph"/> getResourceBundles().addJavaScriptBundle(WicketApplication.class, + <span class="java-quote">"jqueryUiJs"</span>, + jqueryJsReference, + jqueryUiJsReference);<p class="paragraph"/> getResourceBundles().addCssBundle(WicketApplication.class, + <span class="java-quote">"jqueryUiCss"</span>, + jqueryCssReference, + jqueryUiCssReference);<p class="paragraph"/>}</pre></div><p class="paragraph"/>To declare a new resource bundle we need to provide a <em class="italic">scope</em> class (<code>WicketApplication.class</code> in our example) and an unique name. Now, when one of the resources included in the bundle is requested, the entire bundle is rendered instead.<p class="paragraph"/><blockquote class="note"> +A specific resource reference can not be shared among different resource bundles (i.e. it can be part of only one bundle). +</blockquote> + + + +<h2 id="resources_7">15.7 Custom resources</h2> +<p class="paragraph"/>In Wicket the best way to add dynamic functionalities to our application (such as csv export, a pdf generated on the fly, etc...) is implementing a custom resource. In this paragraph as example of custom resource we will build a basic RSS feeds generator which can be used to publish feeds on our site (project CustomResourceMounting). Instead of generating a RSS feed by hand we will use Rome framework and its utility classes.<p class="paragraph"/>As hinted above in paragraph 13.1, class <code>AbstractResource</code> can be used as base class to implement new resources. This class defines abstract method <code>newResourceResponse</code> which is invoked when the resource is requested. The following is the code of our RSS feeds generator:<p class="paragraph"/><div class="code"><pre><span class="java-keyword">public</span> class RSSProducerResource <span class="java-keyword">extends</span> AbstractResource {<p class="paragraph"/> @Override + <span class="java-keyword">protected</span> ResourceResponse newResourceResponse(Attributes attributes) { + ResourceResponse resourceResponse = <span class="java-keyword">new</span> ResourceResponse(); + resourceResponse.setContentType(<span class="java-quote">"text/xml"</span>); + resourceResponse.setTextEncoding(<span class="java-quote">"utf-8"</span>);<p class="paragraph"/> resourceResponse.setWriteCallback(<span class="java-keyword">new</span> WriteCallback() + { + @Override + <span class="java-keyword">public</span> void writeData(Attributes attributes) <span class="java-keyword">throws</span> IOException + { + OutputStream outputStream = attributes.getResponse().getOutputStream(); + Writer writer = <span class="java-keyword">new</span> OutputStreamWriter(outputStream); + SyndFeedOutput output = <span class="java-keyword">new</span> SyndFeedOutput(); + <span class="java-keyword">try</span> { + output.output(getFeed(), writer); + } <span class="java-keyword">catch</span> (FeedException e) { + <span class="java-keyword">throw</span> <span class="java-keyword">new</span> WicketRuntimeException(<span class="java-quote">"Problems writing feed to response..."</span>); + } + } + });<p class="paragraph"/> <span class="java-keyword">return</span> resourceResponse; + } + // method getFeed()… +}</pre></div><p class="paragraph"/>Method <code>newResourceResponse</code> returns an instance of <code>ResourceResponse</code> representing the response generated by the custom resource. Since RSS feeds are based on XML, in the code above we have set the type of the response to text/xml and the text encoding to utf-8.<p class="paragraph"/>To specify the content that will be returned by our resource we must also provide an implementation of inner class <code>WriteCallback</code> which is responsible for writing content data to response's output stream. In our project we used class SyndFeedOutput from Rome framework to write our feed to response. Method <code>getFeed()</code> is just an utility method that generates a sample RSS feed (which is an instance of interface <code>com.sun.syndication.feed.synd.SyndFeed</code>).<p class="paragraph"/>Now that we have our custom resource in place, we can use it in the home page of the project. The easiest way to make a resource available to users is to expose it with link component <code>ResourceLink</code>:<p class="paragraph"/><div class="code"><pre>add(<span class="java-keyword">new</span> ResourceLink(<span class="java-quote">"rssLink"</span>, <span class="java-keyword">new</span> RSSProducerResource()));</pre></div><p class="paragraph"/>In the next paragraphs we will see how to register a resource at application-level and how to mount it to an arbitrary URL. + + +<h2 id="resources_8">15.8 Mounting resources</h2> +<p class="paragraph"/>Just like pages also resources can be mounted to a specific path. Class <code>WebApplication</code> provides method <code>mountResource</code> which is almost identical to <code>mountPage</code> seen in paragraph 8.6.1:<p class="paragraph"/><div class="code"><pre>@Override +<span class="java-keyword">public</span> void init() { + <span class="java-keyword">super</span>.init(); + //resource mounted to path /foo/bar + ResourceReference resourceReference = <span class="java-keyword">new</span> ResourceReference(<span class="java-quote">"rssProducer"</span>){ + RSSReaderResource rssResource = <span class="java-keyword">new</span> RSSReaderResource(); + @Override + <span class="java-keyword">public</span> IResource getResource() { + <span class="java-keyword">return</span> rssResource; + }}; + mountResource(<span class="java-quote">"/foo/bar"</span>, resourceReference); +}</pre></div><p class="paragraph"/>With the configuration above (taken from project <code>CustomResourceMounting</code>) every request to /foo/bar will be served by the custom resource built in the previous paragraph.<p class="paragraph"/>Parameter placeholders are supported as well:<p class="paragraph"/><div class="code"><pre>@Override +<span class="java-keyword">public</span> void init() { + <span class="java-keyword">super</span>.init(); + //resource mounted to path /foo with a required indexed parameter + ResourceReference resourceReference = <span class="java-keyword">new</span> ResourceReference(<span class="java-quote">"rssProducer"</span>){ + RSSReaderResource rssResource = <span class="java-keyword">new</span> RSSReaderResource(); + @Override + <span class="java-keyword">public</span> IResource getResource() { + <span class="java-keyword">return</span> rssResource; + }}; + mountResource(<span class="java-quote">"/bar/${baz}"</span>, resourceReference); +}</pre></div> + + +<h2 id="resources_9">15.9 Shared resources</h2> +<p class="paragraph"/>Resources can be added to a global registry in order to share them at application-level. Shared resources are identified by an application-scoped key and they can be easily retrieved at a later time using reference class <code>SharedResourceReference</code>. The global registry can be accessed with <code>Application</code>'s method <code>getSharedResources</code>. In the following excerpt of code (taken again from project <code>CustomResourceMounting</code>) we register an instance of our custom RSS feeds producer as application-shared resource:<p class="paragraph"/><div class="code"><pre>//init application's method + @Override + <span class="java-keyword">public</span> void init(){ + RSSProducerResource rssResource = <span class="java-keyword">new</span> RSSProducerResource(); + // … + getSharedResources().add(<span class="java-quote">"globalRSSProducer"</span>, rssResource); + }</pre></div><p class="paragraph"/>Now to use an application-shared resource we can simply retrieve it using class <code>SharedResourceReference</code> and providing the key previously used to register the resource:<p class="paragraph"/><div class="code"><pre>add(<span class="java-keyword">new</span> ResourceLink(<span class="java-quote">"globalRssLink"</span>, <span class="java-keyword">new</span> SharedResourceReference(<span class="java-quote">"globalRSSProducer"</span>)));</pre></div><p class="paragraph"/>The URL generated for application shared resources follows the same pattern seen for package resources:<p class="paragraph"/><code>./wicket/resource/org.apache.wicket.Application/globalRSSProducer</code><p class="paragraph"/>The last segment of the URL is the key of the resource while the previous segment contains the scope of the resource. For application-scoped resources the scope is always the fully qualified name of class <code>Application</code>. Thi s should not be surprising since global resources are visible at application level (i.e. the scope is the application).<p class="paragraph"/><blockquote class="note"> +Package resources are also application-shared resources but they don't need to be explicitly registered. +</blockquote><p class="paragraph"/><blockquote class="note"> +Remember that we can get the URL of a resource reference using method <code>urlFor(ResourceReference resourceRef, PageParameters params )</code> available with both class <code>RequestCycle</code> and class <code>Component</code>. +</blockquote> + + +<h2 id="resources_10">15.10 Customizing resource loading</h2> +<p class="paragraph"/>Wicket loads application's resources delegating this task to a resource locator represented by interface <code>org.apache.wicket.core.util.resource.locator.IResourceStreamLocator</code>. To retrieve or modify the current resource locator we can use the getter and setter methods defined by setting interface <code>IResourceSettings</code>:<p class="paragraph"/><div class="code"><pre>//init application's method + @Override + <span class="java-keyword">public</span> void init(){ + //get the resource locator + getResourceSettings().getResourceStreamLocator(); + //set the resource locator + getResourceSettings().setResourceStreamLocator(myLocator); + }</pre></div><p class="paragraph"/>The default locator used by Wicket is class <code>ResourceStreamLocator</code> which in turn tries to load a requested resource using a set of implementations of interface <code>IResourceFinder</code>. This interface defines method <code>find(Class class, String pathname)</code> which tries to resolve a resource corresponding to the given class and path.<p class="paragraph"/>The default implementation of <code>IResourceFinder</code> used by Wicket is <code>ClassPathResourceFinder</code> which searches for resources into the application class path. This is the implementation we have used so far in our examples. However some developers may prefer storing markup files and other resources in a separate folder rather than placing them side by side with Java classes.<p class="paragraph"/>To customize resource loading we can add further resource finders to our application in order to extend the resource-lookup algorithm to different locations. Wick et already comes with two other implementations of IResourceFinder designed to search for resources into a specific folder on the file system. The first is class <code>Path</code> and it's defined in package <code>org.apache.wicket.util.file</code>. The constructor of this class takes in input an arbitrary folder that can be expressed as a string path or as an instance of Wicket utility class <code>Folder</code> (in package <code>org.apache.wicket.util.file</code>). The second implementation of interface <code>IResourceFinder</code> is class <code>WebApplicationPath</code> which looks into a folder placed inside webapp's root path (but not inside folder WEB-INF).<p class="paragraph"/>Project CustomFolder4MarkupExample uses <code>WebApplicationPath</code> to load the markup file and the resource bundle for its home page from a custom folder. The folder is called markupFolder and it is placed in the root path of the webapp. The following picture illustrates the file structure of the p roject:<p class="paragraph"/><img border="0" class="center" src="../img/package-structure-custom-folder.png"></img><p class="paragraph"/>As we can see in the picture above, we must preserve the package structure also in the custom folder used as resource container. The code used inside application class to configure WebApplicationPath is the following:<p class="paragraph"/><div class="code"><pre>@Override +<span class="java-keyword">public</span> void init() +{ + getResourceSettings().getResourceFinders().add( + <span class="java-keyword">new</span> WebApplicationPath(getServletContext(), <span class="java-quote">"markupFolder"</span>)); +}</pre></div><p class="paragraph"/>Method getResourceFinders() defined by setting interface IResourceSettings returns the list of resource finders defined in our application. The constructor of WebApplicationPath takes in input also an instance of standard interface javax.servlet.ServletContext which can be retrieved with WebApplication's method getServletContext().<p class="paragraph"/><blockquote class="note"> +By default, if resource files can not be found inside application classpath, Wicket will search for them inside âresourcesâ folder. You may have noted this folder in the previous picture. It is placed next to the folder âjavaâ containing our source files:<p class="paragraph"/><img border="0" class="center" src="../img/package-structure-resource-folder.png"></img><p class="paragraph"/>This folder can be used to store resource files without writing any configuration code. +</blockquote> + + +<h2 id="resources_11">15.11 Summary</h2> +In this chapter we have learnt how to manage resources with the built-in mechanism provided by Wicket. With this mechanism we handle resources from Java code and Wicket will automatically take care of generating a valid URL for them. We have also seen how resources can be bundled as package resources with a component that depends on them to make it self-contained.<p class="paragraph"/>Then, in the second part of the chapter, we have built a custom resource and we have learnt how to mount it to an arbitrary URL and how to make it globally available as shared resource.<p class="paragraph"/>Finally, in the last part of the paragraph we took a peek at the mechanism provided by the framework to customize the locations where the resource-lookup algorithm searches for resources. + + + + <div style="clear:both;margin-top:15px;"></div> + + <div class="toc-item prev-left"><a href="../guide/i18n.html"><< <strong>14</strong><span>Internationalization with Wicket</span></a></div> + + <div class="toc-item next-right"><a href="../guide/jsintegration.html"><strong>16</strong><span>An example of integration with JavaScript</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 © 2013-2014 â <a href="http://www.apache.org/" target="_blank">The Apache Software Foundation</a> + â <b style="color:#E8590A !important;">(Generated on: 2014-01-28)</b> + + +</div> + +<script type="text/javascript" src="../js/docs.js"></script> + +</body> +</html>
