Repository: wicket Updated Branches: refs/heads/master 147f6d33f -> 4e62461c7
Format inline source code italic Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/4e62461c Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/4e62461c Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/4e62461c Branch: refs/heads/master Commit: 4e62461c7359ff99415ffcd9f9bbc6818593919e Parents: 147f6d3 Author: Jan Mewes <[email protected]> Authored: Wed Nov 7 07:26:46 2018 +0100 Committer: Jan Mewes <[email protected]> Committed: Wed Nov 7 07:35:21 2018 +0100 ---------------------------------------------------------------------- .../componentLifecycle_2.adoc | 8 ++-- .../main/asciidoc/helloWorld/helloWorld_2.adoc | 13 +++--- .../src/main/asciidoc/requestProcessing.adoc | 4 +- .../requestProcessing/requestProcessing_1.adoc | 2 +- .../requestProcessing/requestProcessing_3.adoc | 28 ++++++------- .../requestProcessing/requestProcessing_4.adoc | 37 ++++++++--------- .../versioningCaching/versioningCaching_1.adoc | 6 +-- .../versioningCaching/versioningCaching_2.adoc | 43 ++++++++++---------- .../versioningCaching/versioningCaching_3.adoc | 13 +++--- .../versioningCaching/versioningCaching_4.adoc | 5 +-- 10 files changed, 76 insertions(+), 83 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/4e62461c/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_2.adoc ---------------------------------------------------------------------- diff --git a/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_2.adoc b/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_2.adoc index 0224dbd..ce43954 100644 --- a/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_2.adoc +++ b/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_2.adoc @@ -6,10 +6,10 @@ In the following table these methods are grouped according to the stage in which |=== |*Cycle stage* | *Involved methods* -|Initialization | constructor, onInitialize() -|Rendering | onConfigure(), onBeforeRender(), renderHead(), onRender(), onComponentTag(), onComponentTagBody(), onAfterRender() -|Removed | onRemove() -|Detached | onDetach() +|Initialization | constructor, _onInitialize()_ +|Rendering | _onConfigure()_, _onBeforeRender()_, _renderHead()_, _onRender()_, _onComponentTag()_, _onComponentTagBody()_, _onAfterRender()_ +|Removed | _onRemove()_ +|Detached | _onDetach()_ |=== Now let's take a closer look at each stage and its hook methods. http://git-wip-us.apache.org/repos/asf/wicket/blob/4e62461c/wicket-user-guide/src/main/asciidoc/helloWorld/helloWorld_2.adoc ---------------------------------------------------------------------- diff --git a/wicket-user-guide/src/main/asciidoc/helloWorld/helloWorld_2.adoc b/wicket-user-guide/src/main/asciidoc/helloWorld/helloWorld_2.adoc index 356f536..0824faa 100644 --- a/wicket-user-guide/src/main/asciidoc/helloWorld/helloWorld_2.adoc +++ b/wicket-user-guide/src/main/asciidoc/helloWorld/helloWorld_2.adoc @@ -5,7 +5,7 @@ NOTE: All the example projects presented in this document have been generated us === Wicket application structure -A Wicket application is a standard Java EE web application, hence it is deployed through a web.xml file placed inside folder WEB-INF: +A Wicket application is a standard Java EE web application, hence it is deployed through a _web.xml_ file placed inside folder WEB-INF: image::../img/webinf.png[] @@ -39,11 +39,11 @@ If we are using Servlet 3 or a later version, we can of course use a class in pl [source,java] ---- -@WebFilter(value = "/*", initParams = { - @WebInitParam(name = "applicationClassName", value = "com.mycompany.WicketApplication"), +@WebFilter(value = "/*", initParams = { + @WebInitParam(name = "applicationClassName", value = "com.mycompany.WicketApplication"), @WebInitParam(name="filterMappingUrlPattern", value="/*") }) public class ProjectFilter extends WicketFilter { - + } ---- @@ -53,7 +53,7 @@ NOTE: Wicket can be started in two modes named respectively DEVELOPMENT and DEPL === The application class -If we look back at web.xml we can see that we have provided the Wicket filter with a parameter called _applicationClassName_. This value must be the fully qualified class name of a subclass of _org.apache.wicket.Application_. This subclass represents our web application built upon Wicket and it's responsible for configuring it when the server is starting up. Most of the times our custom application class won't inherit directly from class _Application_, but rather from class _org.apache.wicket.protocol.http.WebApplication_ which provides a closer integration with servlet infrastructure. +If we look back at _web.xml_ we can see that we have provided the Wicket filter with a parameter called _applicationClassName_. This value must be the fully qualified class name of a subclass of _org.apache.wicket.Application_. This subclass represents our web application built upon Wicket and it's responsible for configuring it when the server is starting up. Most of the times our custom application class won't inherit directly from class _Application_, but rather from class _org.apache.wicket.protocol.http.WebApplication_ which provides a closer integration with servlet infrastructure. Class _Application_ comes with a set of configuration methods that we can override to customize our application's settings. One of these methods is _getHomePage()_ that must be overridden as it is declared abstract: [source,java] @@ -76,7 +76,7 @@ The current application's instance can be retrieved at any time by calling stati [source,java] ---- public class WicketApplication extends WebApplication -{ +{ @Override public Class<? extends WebPage> getHomePage() { @@ -96,4 +96,3 @@ Since this is a very basic example of a Wicket application, we don't need to spe NOTE: Declaring a _WicketFilter_ inside web.xml descriptor is not the only way we have to kick-start our application. If we prefer to use a servlet instead of a filter, we can use class _org.apache.wicket.protocol.http.WicketServlet_. See the JavaDoc for further details. - http://git-wip-us.apache.org/repos/asf/wicket/blob/4e62461c/wicket-user-guide/src/main/asciidoc/requestProcessing.adoc ---------------------------------------------------------------------- diff --git a/wicket-user-guide/src/main/asciidoc/requestProcessing.adoc b/wicket-user-guide/src/main/asciidoc/requestProcessing.adoc index 64aaaab..07cdcff 100644 --- a/wicket-user-guide/src/main/asciidoc/requestProcessing.adoc +++ b/wicket-user-guide/src/main/asciidoc/requestProcessing.adoc @@ -1,5 +1,5 @@ -Although Wicket was born to provide a reliable and comprehensive object oriented abstraction for web development, sometimes we might need to work directly with ârawâ web entities such as user session, web request, query parameters, and so on. For example this is necessary if we want to store an arbitrary parameter in the user session. +Although Wicket was born to provide a reliable and comprehensive object oriented abstraction for web development, sometimes we might need to work directly with ârawâ web entities such as user session, web request, query parameters, and so on. For example this is necessary if we want to store an arbitrary parameter in the user session. -Wicket provides wrapper classes that allow us to easily access to web entities without the burden of using the low-level APIs of Java Servlet Specification. However it will always be possible to access standard classes (like HttpSession, HttpServletRequest, etc...) that lay under our Wicket application. +Wicket provides wrapper classes that allow us to easily access to web entities without the burden of using the low-level APIs of Java Servlet Specification. However it will always be possible to access standard classes (like _HttpSession_, _HttpServletRequest_, etc...) that lay under our Wicket application. This chapter will introduce these wrapper classes and it will explain how Wicket uses them to handle the web requests initiated by the user's browser. http://git-wip-us.apache.org/repos/asf/wicket/blob/4e62461c/wicket-user-guide/src/main/asciidoc/requestProcessing/requestProcessing_1.adoc ---------------------------------------------------------------------- diff --git a/wicket-user-guide/src/main/asciidoc/requestProcessing/requestProcessing_1.adoc b/wicket-user-guide/src/main/asciidoc/requestProcessing/requestProcessing_1.adoc index 6cbf9da..0fded65 100644 --- a/wicket-user-guide/src/main/asciidoc/requestProcessing/requestProcessing_1.adoc +++ b/wicket-user-guide/src/main/asciidoc/requestProcessing/requestProcessing_1.adoc @@ -1,6 +1,6 @@ -Beside configuring and initializing our application, the Application class is responsible for creating the internal entities used by Wicket to process a request. These entities are instances of the following classes: RequestCycle, Request, Response and Session. +Beside configuring and initializing our application, the _Application_ class is responsible for creating the internal entities used by Wicket to process a request. These entities are instances of the following classes: _RequestCycle_, _Request_, _Response_ and _Session_. The next paragraphs will illustrate each of these classes, explaining how they are involved into request processing. http://git-wip-us.apache.org/repos/asf/wicket/blob/4e62461c/wicket-user-guide/src/main/asciidoc/requestProcessing/requestProcessing_3.adoc ---------------------------------------------------------------------- diff --git a/wicket-user-guide/src/main/asciidoc/requestProcessing/requestProcessing_3.adoc b/wicket-user-guide/src/main/asciidoc/requestProcessing/requestProcessing_3.adoc index 761e13d..5d07291 100644 --- a/wicket-user-guide/src/main/asciidoc/requestProcessing/requestProcessing_3.adoc +++ b/wicket-user-guide/src/main/asciidoc/requestProcessing/requestProcessing_3.adoc @@ -1,7 +1,7 @@ -Class _org.apache.wicket.request.cycle.RequestCycle_ is the entity in charge of serving a web request. Our application class creates a new _RequestCycle_ on every request with its method _createRequestCycle(request, response)_. +Class _org.apache.wicket.request.cycle.RequestCycle_ is the entity in charge of serving a web request. Our application class creates a new _RequestCycle_ on every request with its method _createRequestCycle(request, response)_. Method _createRequestCycle_ is declared as final, so we can't override it to return a custom subclass of _RequestCycle_. Instead, we must build a request cycle provider implementing interface _org.apache.wicket.IRequestCycleProvider_, and then we must tell our application class to use it via the _setRequestCycleProvider_ method. @@ -22,7 +22,7 @@ public final RequestCycle getRequestCycle() { NOTE: This paragraph will provide just the basic informations about what happens behind the scenes of request processing. When you work with Wicket it's unlikely to have a need for customizing this process, so we won't cover this topic in detail. -In order to process a request, _RequestCycle_ delegates the task to another entity which implements interface _org.apache.wicket.request.IRequestHandler_. There are different implementations of this interface, each suited for a particular type of requested resource (a page to render, an AJAX request, an URL to an external page, etc.). +In order to process a request, _RequestCycle_ delegates the task to another entity which implements interface _org.apache.wicket.request.IRequestHandler_. There are different implementations of this interface, each suited for a particular type of requested resource (a page to render, an AJAX request, an URL to an external page, etc.). To resolve the right handler for a given HTTP request, the _RequestCycle_ uses a set of objects implementing the _org.apache.wicket.request.IRequestMapper_ interface. The mapping interface defines the _getCompatibilityScore(Request request)_ method which returns a score indicating how compatible the request mapper is for the current request. _RequestCycle_ will choose the mapper with the highest score and it will call its _mapRequest(Request request)_ method to get the proper handler for the given request. Once _RequestCycle_ has resolved a request handler, it invokes its method _respond(IRequestCycle requestCycle)_ to start request processing. @@ -30,16 +30,16 @@ The following sequence diagram recaps how a request handler is resolved by the _ image::../img/request-cycle-handler.png[] -Developers can create additional implementations of IRequestMapper and add them to their application via the mount(IRequestMapper mapper) method of the WebApplication class. In paragraph 10.6 we will see how Wicket uses this method to add built-in mappers for mounted pages. +Developers can create additional implementations of _IRequestMapper_ and add them to their application via the _mount(IRequestMapper mapper)_ method of the _WebApplication_ class. In paragraph 10.6 we will see how Wicket uses this method to add built-in mappers for mounted pages. === Generating URL with the urlFor and mapUrlFor methods -The RequestCycle is also responsible for generating the URL value (as CharSequence) for the following entities: +The _RequestCycle_ is also responsible for generating the URL value (as _CharSequence_) for the following entities: -* a page class, via the _urlFor(Class<C> pageClass, PageParameters parameters)_ method -* an IRequestHandler via the _urlFor(IRequestHandler handler)_ method -* a ResourceReference via the _urlFor(ResourceReference reference, PageParameters params)_ method (resource entities will be introduced in -<<_resource_management_with_wicket,chapter 19>>). +* a page class, via the _urlFor(Class<C> pageClass, PageParameters parameters)_ method +* an _IRequestHandler_ via the _urlFor(IRequestHandler handler)_ method +* a _ResourceReference_ via the _urlFor(ResourceReference reference, PageParameters params)_ method (resource entities will be introduced in +<<_resource_management_with_wicket,chapter 19>>). The overloaded _urlFor_ method from above also has a corresponding version that returns an instance of _org.apache.wicket.request.Url_ instead of a _CharSequence_. This version has the prefix 'map' in its name (i.e. it has _mapUrlFor_ as full name). @@ -56,13 +56,13 @@ public final void setResponsePage(final Page page) { === RequestCycle's hook methods and listeners -The RequestCycle comes with some hook methods which can be overridden to perform custom actions when request handling reaches a specific stage. These methods are: +The _RequestCycle_ comes with some hook methods which can be overridden to perform custom actions when request handling reaches a specific stage. These methods are: -* *onBeginRequest():* called when the RequestCycle is about to start handling the request. +* *onBeginRequest():* called when the RequestCycle is about to start handling the request. * *onEndRequest():* called when the RequestCycle has finished to handle the request * *onDetach():* called after the request handling has completed and the RequestCycle is about to be detached from its thread. The default implementation of this method invokes detach() on the current session (the Session class will be shortly discussed in paragraph 9.4). -Methods onBeforeRequest and onEndRequest can be used if we need to execute custom actions before and after business code is executed, such as opening a Hibernate/JPA session and closing it when code has terminated. +Methods onBeforeRequest and onEndRequest can be used if we need to execute custom actions before and after business code is executed, such as opening a Hibernate/JPA session and closing it when code has terminated. A more flexible way to interact with the request processing is to use the listener interface _org.apache.wicket.request.cycle.IRequestCycleListener_. In addition to the three methods already seen for RequestCycle, this interface offers further hooks into request processing: @@ -73,7 +73,7 @@ A more flexible way to interact with the request processing is to use the listen * *onRequestHandlerScheduled(RequestCycle cycle, IRequestHandler handler):* called when an IRequestHandler has been scheduled for execution. * *onRequestHandlerExecuted(RequestCycle cycle, IRequestHandler handler):* called when an IRequestHandler has been executed. * *onException(RequestCycle cycle, Exception ex):* called when an exception has been thrown during request processing. -* *onExceptionRequestHandlerResolved(RequestCycle rc, IRequestHandler rh, Exception ex):* called when an IRequestHandler has been resolved and will be used to handle an exception. +* *onExceptionRequestHandlerResolved(RequestCycle rc, IRequestHandler rh, Exception ex):* called when an IRequestHandler has been resolved and will be used to handle an exception. * *onUrlMapped(RequestCycle cycle, IRequestHandler handler, Url url):* called when an URL has been generated for an IRequestHandler object. To use the request cycle listeners we must add them to our application which in turn will pass them to the new _RequestCycle_'s instances created with _createRequestCycle_ method: @@ -87,10 +87,8 @@ public void init() { IRequestCycleListener myListener; //listener initialization... - getRequestCycleListeners().add(myListener) + getRequestCycleListeners().add(myListener) } ---- The _getRequestCycleListeners_ method returns an instance of class _org.apache.wicket.request.cycle.RequestCycleListenerCollection_. This class is a sort of typed collection for _IRequestCycleListener_ and it also implements the http://en.wikipedia.org/wiki/Composite_pattern[Composite pattern] . - - http://git-wip-us.apache.org/repos/asf/wicket/blob/4e62461c/wicket-user-guide/src/main/asciidoc/requestProcessing/requestProcessing_4.adoc ---------------------------------------------------------------------- diff --git a/wicket-user-guide/src/main/asciidoc/requestProcessing/requestProcessing_4.adoc b/wicket-user-guide/src/main/asciidoc/requestProcessing/requestProcessing_4.adoc index 3e30614..c26c312 100644 --- a/wicket-user-guide/src/main/asciidoc/requestProcessing/requestProcessing_4.adoc +++ b/wicket-user-guide/src/main/asciidoc/requestProcessing/requestProcessing_4.adoc @@ -1,11 +1,11 @@ -In Wicket we use class _org.apache.wicket.Session_ to handle session-relative informations such as client informations, session attributes, session-level cache (seen in paragraph 8.2), etc... +In Wicket we use class _org.apache.wicket.Session_ to handle session-relative informations such as client informations, session attributes, session-level cache (seen in paragraph 8.2), etc... In addition, we know from paragraph 8.1 that Wicket creates a user session to store versions of stateful pages. Similarly to what happens with RequestCycle, the new Session's instances are generated by the _Application_ class with the _newSession(Request request, Response response)_ method. This method is not declared as final, hence it can be overridden if we need to use a custom implementation of the Session class. -By default if our custom application class is a subclass of WebApplication, method newSession will return an instance of class _org.apache.wicket.protocol.http.WebSession_. As we have mentioned talking about _RequestCycle_, also class Session provides a static _get()_ method which returns the session associated to the current thread. +By default if our custom application class is a subclass of _WebApplication_, method _newSession_ will return an instance of class _org.apache.wicket.protocol.http.WebSession_. As we have mentioned talking about _RequestCycle_, also class Session provides a static _get()_ method which returns the session associated to the current thread. === Session and listeners @@ -17,28 +17,28 @@ Similar to the _RequestCycle_, class _org.apache.wicket.Session_ also offers sup public void init(){ super.init(); - + //listener initialization... ISessionListener myListener; //add a custom session listener getSessionListeners().add(myListener) - + } ---- === Handling session attributes -The Session class handles session attributes in much the same way as the standard interface javax.servlet.http.HttpSession. The following methods are provided to create, read and remove session attributes: +The Session class handles session attributes in much the same way as the standard interface _javax.servlet.http.HttpSession_. The following methods are provided to create, read and remove session attributes: * *setAttribute(String name, Serializable value):* creates an attribute identified by the given name. If the session already contains an attribute with the same name, the new value will replace the existing one. The value must be a serializable object. -* *getAttribute(String name):* returns the value of the attribute identified by the given name, or null if the name does not correspond to any attribute. +* *getAttribute(String name):* returns the value of the attribute identified by the given name, or _null_ if the name does not correspond to any attribute. * *removeAttribute(String name):* removes the attribute identified by the given name. By default class WebSession will use the underlying HTTP session to store attributes. Wicket will automatically add a prefix to the name of the attributes. This prefix is returned by the WebApplication's method getSessionAttributePrefix(). === Accessing to the HTTP session -If for any reason we need to directly access to the underlying HttpSession object, we can retrieve it from the current request with the following code: +If for any reason we need to directly access to the underlying _HttpSession_ object, we can retrieve it from the current request with the following code: [source,java] ---- @@ -50,12 +50,12 @@ Using the raw session object might be necessary if we have to set a session attr image::../img/tomcat-admin-sessions.png[] -Tomcat allows us to set the values that will be displayed in columns âGuessed localeâ and âGuessed User nameâ. One possible way to do this is to use session attributes named âLocaleâ and âuserNameâ but we can't create them via Wicket's Session class because they would not have exactly the name required by Tomcat. Instead, we must use the raw HttpSession and set our attributes on it: +Tomcat allows us to set the values that will be displayed in columns âGuessed localeâ and âGuessed User nameâ. One possible way to do this is to use session attributes named âLocaleâ and âuserNameâ but we can't create them via Wicket's Session class because they would not have exactly the name required by Tomcat. Instead, we must use the raw _HttpSession_ and set our attributes on it: [source,java] ---- HttpSession session = ((ServletWebRequest)RequestCycle.get(). - getRequest()).getContainerRequest().getSession(); + getRequest()).getContainerRequest().getSession(); session.setAttribute("Locale", "ENGLISH"); session.setAttribute("userName", "Mr BadGuy"); @@ -70,11 +70,11 @@ Wicket doesn't need to store data into user session as long as the user visits o Session.get().isTemporary(); ---- -If a session is not temporary (i.e. it is permanent), it's identified by an unique id which can be read calling the getId() method. This value will be null if the session is temporary. +If a session is not temporary (i.e. it is permanent), it's identified by an unique id which can be read calling the getId() method. This value will be _null_ if the session is temporary. -Although Wicket is able to automatically recognize when it needs to replace a temporary session with a permanent one, sometimes we may need to manually control this process to make our initially temporary session permanent. +Although Wicket is able to automatically recognize when it needs to replace a temporary session with a permanent one, sometimes we may need to manually control this process to make our initially temporary session permanent. -To illustrate this possible scenario let's consider project BindSessionExample where we have a stateless home page which sets a session attribute inside its constructor and then it redirects the user to another page which displays with a label the session attribute previously created. The code of the two pages is as follows: +To illustrate this possible scenario let's consider project "BindSessionExample" where we have a stateless home page which sets a session attribute inside its constructor and then it redirects the user to another page which displays with a label the session attribute previously created. The code of the two pages is as follows: Home page: [source,java] @@ -83,9 +83,9 @@ public class HomePage extends WebPage { public HomePage(final PageParameters parameters) { Session.get().setAttribute("username", "tommy"); Session.get().bind(); - + setResponsePage(DisplaySessionParameter.class); - } + } } ---- @@ -102,7 +102,7 @@ public class DisplaySessionParameter extends WebPage { } ---- -Again, we kept page logic very simple to not over-bloat the example with unnecessary code. In the snippet above we have also bolded Session's bind() method which converts temporary session into a permanent one. If the home page has not invoked this method, the session with its attribute would have been discarded at the end of the request and the page DisplaySessionParameter would have displayed an empty value in its label. +Again, we kept page logic very simple to not over-bloat the example with unnecessary code. In the snippet above we have also bolded Session's bind() method which converts temporary session into a permanent one. If the home page has not invoked this method, the session with its attribute would have been discarded at the end of the request and the page _DisplaySessionParameter_ would have displayed an empty value in its label. === Discarding session data @@ -115,7 +115,7 @@ WARNING: Remember that invalidateNow() will immediately remove any instance of c JavaServer Pages Specification1 defines 4 scopes in which a page can create and access a variable. These scopes are: * *request:* variables declared in this scope can be seen only by pages processing the same request. The lifespan of these variables is (at most) equal to the one of the related request. They are discarded when the full response has been generated or when the request is forwarded somewhere else. -* *page:* variables declared in this scope can be seen only by the page that has created them. +* *page:* variables declared in this scope can be seen only by the page that has created them. * *session:* variables in session scope can be created and accessed by every page used in the same session where they are defined. * *application:* this is the widest scope. Variables declared in this scope can be used by any page of a given web application. @@ -140,13 +140,13 @@ public static MetaDataApp extends WebApplication{ */ @Override public void init(){ - + super.init(); Connection connection; //connection initialization... setMetaData(connectionKey, connection); //Do some other stuff.. - + } } ---- @@ -159,4 +159,3 @@ Connection connection = Application.get().getMetaData(MetaDataApp.connectionKey) ---- Since MetaDataKey<T> class is declared as abstract, we must implement it with a subclass or with an anonymous class (like we did in the example above). - http://git-wip-us.apache.org/repos/asf/wicket/blob/4e62461c/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_1.adoc ---------------------------------------------------------------------- diff --git a/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_1.adoc b/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_1.adoc index 97a0561..a497e84 100644 --- a/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_1.adoc +++ b/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_1.adoc @@ -2,9 +2,9 @@ Wicket pages can be divided into two categories: stateful and stateless pages. Stateful pages are those which rely on user session to store their internal state and to keep track of user interaction. -On the contrary stateless pages are those which don't change their internal state during their lifecycle and they don't need to occupy space into user session. +On the contrary stateless pages are those which don't change their internal state during their lifecycle and they don't need to occupy space into user session. -From Wicket's point of view the biggest difference between these two types of page is that stateful pages are versioned, meaning that they will be saved into user session every time their internal state has changed. Wicket automatically assigns a session to the user the first time a stateful page is requested. Page versions are stored into user session using Java Serialization mechanism. -Stateless pages are never versioned and that's why they don't require a valid user session. If we want to know whether a page is stateless or not, we can call the isPageStateless() method of class Page. +From Wicket's point of view the biggest difference between these two types of page is that stateful pages are versioned, meaning that they will be saved into user session every time their internal state has changed. Wicket automatically assigns a session to the user the first time a stateful page is requested. Page versions are stored into user session using Java Serialization mechanism. +Stateless pages are never versioned and that's why they don't require a valid user session. If we want to know whether a page is stateless or not, we can call the _isPageStateless()_ method of class _Page_. In order to build a stateless page we must comply with some rules to ensure that the page won't need to use user session. These rules are illustrated in paragraph 8.3 but before talking about stateless pages we must first understand how stateful pages are handled and why they are versioned. http://git-wip-us.apache.org/repos/asf/wicket/blob/4e62461c/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_2.adoc ---------------------------------------------------------------------- diff --git a/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_2.adoc b/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_2.adoc index 499f166..4842b49 100644 --- a/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_2.adoc +++ b/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_2.adoc @@ -1,15 +1,15 @@ -Stateful pages are versioned in order to support browser's back button: when this button is pressed Wicket must respond by rendering the same page instance previously used. +Stateful pages are versioned in order to support browser's back button: when this button is pressed Wicket must respond by rendering the same page instance previously used. -A new page version is created when a stateful page is requested for the first time or when an existing instance is modified (for example changing its component hierarchy). To identify each page version Wicket uses a session-relative identifier called page id. This is a unique number and it is increased every time a new page version is created. +A new page version is created when a stateful page is requested for the first time or when an existing instance is modified (for example changing its component hierarchy). To identify each page version Wicket uses a session-relative identifier called page id. This is a unique number and it is increased every time a new page version is created. In the final example of the previous chapter (project LifeCycleStages), you may have noticed the number appended at the end of URL. This number is the page id we are talking about: image::../img/page-id.png[] -In this chapter we will use a revised version of this example project where the component hierarchy is modified inside the Link's onClick()method. This is necessary because Wicket creates a new page version only if the page is modified before its method onBeforeRender() is invoked. The code of the new home page is the following: +In this chapter we will use a revised version of this example project where the component hierarchy is modified inside the Link's _onClick()_ method. This is necessary because Wicket creates a new page version only if the page is modified before its method _onBeforeRender()_ is invoked. The code of the new home page is the following: [source,java] ---- @@ -18,24 +18,24 @@ public class HomePage extends WebPage private static final long serialVersionUID = 1L; private Label firstLabel; private Label secondLabel; - + public HomePage(){ firstLabel = new Label("label", "First label"); secondLabel = new Label("label", "Second label"); - + add(firstLabel); - + add(new Link<Void>("reload"){ @Override - public void onClick() { + public void onClick() { if(getPage().contains(firstLabel, true)) getPage().replace(secondLabel); else - getPage().replace(firstLabel); + getPage().replace(firstLabel); } - }); - - } + }); + + } } ---- @@ -47,7 +47,7 @@ If we press the back button the page version previously rendered (and serialized image::../img/browser-back.png[] -NOTE: For more details about page storing you can take a look at paragraph "Page storing" from chapter "Wicket Internals" The content of this paragraph is from wiki page https://cwiki.apache.org/confluence/display/WICKET/Page+Storage. +NOTE: For more details about page storing you can take a look at paragraph "Page storing" from chapter "Wicket Internals" The content of this paragraph is from wiki page https://cwiki.apache.org/confluence/display/WICKET/Page+Storage. As we have stated at the beginning of this chapter, page versions are stored using Java serialization, therefore every object referenced inside a page must be serializable. In <<modelsforms.adoc#_model_chaining,paragraph 11.6>> we will see how to overcome this limit and work with non-serializable objects in our components using detachable Wicket models. @@ -67,13 +67,13 @@ To get the related page instance we must use the method getPage. === Turning off page versioning -If for any reason we need to switch off versioning for a given page, we can call its method setVersioned(false). +If for any reason we need to switch off versioning for a given page, we can call its method _setVersioned(false)_. === Pluggable serialization -Starting from version 1.5 it is possible to choose which implementation of Java serialization will be used by Wicket to store page versions. Wicket serializes pages using an implementation of interface _org.apache.wicket.serialize.ISerializer_. The default implementation is _org.apache.wicket.serialize.java.JavaSerializer_ and it uses the standard Java serialization mechanism based on classes ObjectOutputStream and ObjectInputStream. However on Internet we can find other interesting serialization libraries like https://github.com/EsotericSoftware/kryo[Kryo] +Starting from version 1.5 it is possible to choose which implementation of Java serialization will be used by Wicket to store page versions. Wicket serializes pages using an implementation of interface _org.apache.wicket.serialize.ISerializer_. The default implementation is _org.apache.wicket.serialize.java.JavaSerializer_ and it uses the standard Java serialization mechanism based on classes _ObjectOutputStream_ and _ObjectInputStream_. However on internet we can find other interesting serialization libraries like https://github.com/EsotericSoftware/kryo[Kryo]. -We can access this class inside the method _init_ of the class Application using the getFrameworkSettings() method : +We can access this class inside the method _init_ of the class _Application_ using the _getFrameworkSettings()_ method : [source,java] ---- @@ -89,15 +89,15 @@ A serializer based on Kryo library and another one based on Fast are provided by === Page caching -By default Wicket persists versions of pages into a session-relative file on disk, but it uses a two-levels cache to speed up this process. The first level of the cache uses a http session attribute called âwicket:persistentPageManagerData-<APPLICATION_NAME>â to store pages. The second level cache stores pages into application-scoped variables which are identified by a session id and a page id. +By default Wicket persists versions of pages into a session-relative file on disk, but it uses a two-levels cache to speed up this process. The first level of the cache uses a http session attribute called âwicket:persistentPageManagerData-<APPLICATION_NAME>â to store pages. The second level cache stores pages into application-scoped variables which are identified by a session id and a page id. The following picture is an overview of these two caching levels: image::../img/wicket-cache.png[] -The session-scoped cache is faster then the other memory levels but it contains only the pages used to serve the last request. Wicket allows us to set the maximum amount of memory allowed for the application-scoped cache and for the page store file. Both parameters can be configured via setting class _org.apache.wicket.settings.StoreSettings_. +The session-scoped cache is faster then the other memory levels but it contains only the pages used to serve the last request. Wicket allows us to set the maximum amount of memory allowed for the application-scoped cache and for the page store file. Both parameters can be configured via setting class _org.apache.wicket.settings.StoreSettings_. -This interface provides the setMaxSizePerSession(Bytes bytes) method to set the size for page store file. The Bytes parameter is the maximum size allowed for this file: +This interface provides the _setMaxSizePerSession(Bytes bytes)_ method to set the size for page store file. The Bytes parameter is the maximum size allowed for this file: [source,java] ---- @@ -110,7 +110,7 @@ public void init() ---- Class _org.apache.wicket.util.lang.Bytes_ is an utility class provided by Wicket to express size in bytes (for further details refer to the JavaDoc). -For the second level cache we can use the setInmemoryCacheSize(int inmemoryCacheSize) method. The integer parameter is the maximum number of page instances that will be saved into application-scoped cache: +For the second level cache we can use the _setInmemoryCacheSize(int inmemoryCacheSize)_ method. The integer parameter is the maximum number of page instances that will be saved into application-scoped cache: [source,java] ---- @@ -124,7 +124,7 @@ public void init() === Page expiration -Page instances are not kept in the user session forever. They can be discarded when the limit set with the setMaxSizePerSession method is reached or (more often) when user session expires. When we ask Wicket for a page id corresponding to a page instance removed from the session, we bump into a PageExpiredException and we get the following default error page: +Page instances are not kept in the user session forever. They can be discarded when the limit set with the _setMaxSizePerSession_ method is reached or (more often) when user session expires. When we ask Wicket for a page id corresponding to a page instance removed from the session, we bump into a _PageExpiredException_ and we get the following default error page: image::../img/page-expired.png[] @@ -141,5 +141,4 @@ public void init() } ---- -The page class provided as custom error page must have a public constructor with no argument or a constructor that takes as input a single PageParameters argument (the page must be bookmarkable as described in <<urls.adoc#_pageparameters,paragraph 10.1.1>>). - +The page class provided as custom error page must have a public constructor with no argument or a constructor that takes as input a single _PageParameters_ argument (the page must be bookmarkable as described in <<urls.adoc#_pageparameters,paragraph 10.1.1>>). http://git-wip-us.apache.org/repos/asf/wicket/blob/4e62461c/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_3.adoc ---------------------------------------------------------------------- diff --git a/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_3.adoc b/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_3.adoc index 8ebe4be..62e9060 100644 --- a/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_3.adoc +++ b/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_3.adoc @@ -1,23 +1,23 @@ -Wicket makes it very easy to build stateful pages, but sometimes we might want to use an âold schoolâ stateless page that doesn't keep memory of its state in the user session. For example consider the public area of a site or a login page: in those cases a stateful page would be a waste of resources or even a security threat, as we will see in paragraph <<forms2.adoc#_stateless_form,paragraph 12.10>>. +Wicket makes it very easy to build stateful pages, but sometimes we might want to use an âold schoolâ stateless page that doesn't keep memory of its state in the user session. For example consider the public area of a site or a login page: in those cases a stateful page would be a waste of resources or even a security threat, as we will see in paragraph <<forms2.adoc#_stateless_form,paragraph 12.10>>. In Wicket a page can be stateless only if it satisfies the following requirements: 1. it has been instantiated by Wicket (i.e. we don't create it with operator new) using a constructor with no argument or a constructor that takes as input a single PageParameters argument (class PageParameters will be covered in <<urls.adoc#_pageparameters,chapter 10.1>>). -2. All its children components (and behaviors) are in turn stateless, which means that their method isStateless must return true. +2. All its children components (and behaviors) are in turn stateless, which means that their method _isStateless_ must return _true_. -The first requirement implies that, rather than creating a page by hand, we should rely on Wicket's capability of resolving page instances, like we do when we use method setResponsePage(Class page). +The first requirement implies that, rather than creating a page by hand, we should rely on Wicket's capability of resolving page instances, like we do when we use method _setResponsePage(Class page)_. -In order to comply with the second requirement it could be helpful to check if all children components of a page are stateless. To do this we can leverage method visitChildren and the visitor pattern to iterate over components and test if their method isStateless actually returns true: +In order to comply with the second requirement it could be helpful to check if all children components of a page are stateless. To do this we can leverage method _visitChildren_ and the visitor pattern to iterate over components and test if their method _isStateless_ actually returns _true_: [source,java] ---- @Override protected void onInitialize() { super.onInitialize(); - + visitChildren((component, visit) -> { if(!component.isStateless()) { System.out.println("Component " + component.getId() + " is not stateless"); @@ -40,7 +40,6 @@ public void init() NOTE: Most of the Wicket's built-in components are stateful, hence they can not be used with a stateless page. However some of them have also a stateless version which can be adopted when we need to keep a page stateless. In the rest of the guide we will point out when a built-in component comes also with a stateless version. -A page can be also explicitly declared as stateless setting the appropriate flag to true with the setStatelessHint(true) method. This method will not prevent us from violating the requirements for a stateless page, but if we do so we will get the following warning log message: +A page can be also explicitly declared as stateless setting the appropriate flag to true with the _setStatelessHint(true)_ method. This method will not prevent us from violating the requirements for a stateless page, but if we do so we will get the following warning log message: WARNING: Page '<page class>' is not stateless because of component with path '<component path>' - http://git-wip-us.apache.org/repos/asf/wicket/blob/4e62461c/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_4.adoc ---------------------------------------------------------------------- diff --git a/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_4.adoc b/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_4.adoc index a1ebdd2..99b8b2b 100644 --- a/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_4.adoc +++ b/wicket-user-guide/src/main/asciidoc/versioningCaching/versioningCaching_4.adoc @@ -1,8 +1,7 @@ -In this chapter we have seen how page instances are managed by Wicket. We have learnt that pages can be divided into two families: stateless and stateful pages. Knowing the difference between the two types of pages is important to build the right page for a given task. +In this chapter we have seen how page instances are managed by Wicket. We have learnt that pages can be divided into two families: stateless and stateful pages. Knowing the difference between the two types of pages is important to build the right page for a given task. -However, to complete the discussion about stateless pages we still have to deal with two topics we have just outlined in this chapter: class PageParameters and bookmarkable pages. The first part of +However, to complete the discussion about stateless pages we still have to deal with two topics we have just outlined in this chapter: class _PageParameters_ and bookmarkable pages. The first part of <<_wicket_links_and_url_generation,chapter 10>> will cover these missing topics. -
