Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Tapestry Wiki" for 
change notification.

The "Tapestry5HowToCreateADispatcher" page has been changed by BasileChandesris.
http://wiki.apache.org/tapestry/Tapestry5HowToCreateADispatcher?action=diff&rev1=3&rev2=4

--------------------------------------------------

  When Tapestry recieves a request for a resource (page, etc) a lot happens. 
Before reading this it would be prudent to first read about how requests are 
processed on the main page:
  
- http://tapestry.apache.org/tapestry5/tapestry-core/guide/request.html
+ http://tapestry.apache.org/tapestry5/guide/request.html
  
- For dispatching and handling requests, Tapestry employs a chain of command 
implemented as the 
[[http://tapestry.apache.org/tapestry5/tapestry-core/guide/request.html|MasterDispatcher]]
 service. The framework uses Tapestry IoC to configure itself, and therefore 
has a 
[[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry/services/TapestryModule.html|TapestryModule]]
 (just like your apps have an "!AppModule"). Buried in this module is a method 
for configuring the !MasterDispatcher service: 
[[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry/services/TapestryModule.html#contributeMasterDispatcher(org.apache.tapestry.ioc.OrderedConfiguration,%20org.apache.tapestry.services.ClasspathAssetAliasManager,%20org.apache.tapestry.internal.services.ResourceCache,%20org.apache.tapestry.internal.services.ResourceStreamer,%20org.apache.tapestry.services.PageRenderRequestHandler,%20org.apache.tapestry.services.ComponentActionRequestHandler,%20org.apache.tapestry.services.ComponentClassResolver,%20java.lang.String)|TapestryModule#contributeMasterDispatcher]].
 I strongly recommend looking at the source of this file and especially at the 
contributions to the !MasterDispatcher, as that is how I learned what I am 
about to share.
+ For dispatching and handling requests, Tapestry employs a chain of command 
implemented as the [http://tapestry.apache.org/tapestry5/guide/request.html 
|MasterDispatcher ] service. The framework uses Tapestry IoC to configure 
itself, and therefore has a 
[[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry5/services/TapestryModule.html|TapestryModule]]
 (just like your apps have an "!AppModule"). Buried in this module is a method 
for configuring the !MasterDispatcher service: 
[[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry5/services/TapestryModule.html#contributeMasterDispatcher%28org.apache.tapestry5.ioc.OrderedConfiguration%29|TapestryModule#contributeMasterDispatcher]].
 I strongly recommend looking at the source of this file and especially at the 
contributions to the !MasterDispatcher, as that is how I learned what I am 
about to share.
  
- There are many reasons to intercept requests. Tapestry installs several 
dispatchers to intercept certain kinds of requests, in a certain order. The 
kind of configuration used by the !MasterDispatcher 
([[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry/ioc/OrderedConfiguration.html|OrderedConfiguration]])
 allows us to insert a dispatcher anywhere in the chain, using the 
''before:Id'' or ''after:Id'' syntax (again, read the source and api for more 
information on these).
+ There are many reasons to intercept requests. Tapestry installs several 
dispatchers to intercept certain kinds of requests, in a certain order. The 
kind of configuration used by the !MasterDispatcher 
([[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry5/ioc/OrderedConfiguration.html|OrderedConfiguration]])
 allows us to insert a dispatcher anywhere in the chain, using the 
''before:Id'' or ''after:Id'' syntax (again, read the source and api for more 
information on these).
  I had a personal interest in this because I work with applications that, like 
many, require a login and an access control mechanism. Logging in is easy, its 
implementing the access controls that embodies the real work. In the past I've 
worked with frameworks that have a roughly similar paradigm of pages, and the 
only way to implement access controls without coding logic into each controller 
(or page) class was to implement it in a common base class and subclass that. 
Well, times have changed. I don't like the fact that my pages know about access 
controls, it's none of their business. Tapestry 5 provides the infrastructure 
for a completely transparent access controller, and now we'll create a simple 
one to demonstrate the usefulness of both the configuration mechanism and the 
request processing pipeline in Tapestry 5.
  
- When you look at the source of the 
[[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry/services/TapestryModule.html#contributeMasterDispatcher(org.apache.tapestry.ioc.OrderedConfiguration,%20org.apache.tapestry.services.ClasspathAssetAliasManager,%20org.apache.tapestry.internal.services.ResourceCache,%20org.apache.tapestry.internal.services.ResourceStreamer,%20org.apache.tapestry.services.PageRenderRequestHandler,%20org.apache.tapestry.services.ComponentActionRequestHandler,%20org.apache.tapestry.services.ComponentClassResolver,%20java.lang.String)|TapestryModule#contributeMasterDispatcher]]
 method, you'll notice several dispatchers get installed. The ids of them are:
+ When you look at the source of the 
[[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry5/services/TapestryModule.html#contributeMasterDispatcher%28org.apache.tapestry5.ioc.OrderedConfiguration%29]]
 method, you'll notice several dispatchers get installed. The ids of them are:
  
-  * !RootPath 
([[http://tapestry.apache.org/tapestry5/apidocs/index.html|RootPathDispatcher]])
 - Responsible for rendering the Start page when the app root is requested.
+  * !RootPath 
([[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry5/internal/services/RootPathDispatcher.html|RootPathDispatcher]])
 - Responsible for rendering the Start page when the app root is requested.
-  * Asset 
([[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry/internal/services/AssetDispatcher.html|AssetDispatcher]])
 - Handles serving assets from the classpath, context path, etc.
+  * Asset 
([[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry5/internal/services/AssetDispatcher.html|AssetDispatcher]])
 - Handles serving assets from the classpath, context path, etc.
-  * !PageRender 
([[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry/internal/services/PageRenderDispatcher.html|PageRenderDispatcher]])
 - Responsible for resolving and rendering pages, as the name suggests.
+  * !PageRender 
([[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry5/internal/services/PageRenderDispatcher.html|PageRenderDispatcher]])
 - Responsible for resolving and rendering pages, as the name suggests.
-  * !ComponentAction 
([[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry/internal/services/ComponentActionDispatcher.html|ComponentActionDispatcher]])
 - Responsible for resolving event handlers for page and component actions.
+  * !ComponentEvent 
([[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry5/internal/services/ComponentEventDispatcher.html|ComponentEventDispatcher]])
 - Responsible for resolving event handlers for page and component actions.
  
  These dispatchers are added and executed in this order. While it's certainly 
possible you might want to restrict other types of requests, I'd wager that 
most of the time developers need to protect pages, or entire sections of pages, 
from being accessed by unauthorized users.
  
  Now that you have a decent understanding of what dispatchers are and how they 
work, you should realize that implementing a completely unobtrusive access 
control system is as easy as implementing a 
[[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry/services/Dispatcher.html|Dispatcher]].
 That part I assure you, is easy. The internal architecture of your system may 
very will be quite complex, but hooking it into Tapestry 5 is cake, and this is 
how you do it in a nutshell:
  
  == 1) Implement a Dispatcher ==
- This is a wonderfully brief interface with one method to implement: 
[[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry/services/Dispatcher.html#dispatch(org.apache.tapestry.services.Request,%20org.apache.tapestry.services.Response)|dispatch]].
 As expected, looking at the api/source for this interface, as well as some of 
the implementations will be helpful. For implementing an access controller, its 
essentially as easy as returning false or throwing an exception. Here's summary 
of the possible outcomes of this method:
+ This is a wonderfully brief interface with one method to implement: 
[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry5/services/Dispatcher.html#dispatch%28org.apache.tapestry5.services.Request,%20org.apache.tapestry5.services.Response%29|dispatch]].
 As expected, looking at the api/source for this interface, as well as some of 
the implementations will be helpful. For implementing an access controller, its 
essentially as easy as returning false or throwing an exception. Here's summary 
of the possible outcomes of this method:
  
   * Return true. This will tell Tapestry that the request has been handled and 
no other dispatcher in the chain need be consulted. If you return true from 
your access controller dispatcher, you're likely to get a blank response (and a 
blank page). This is because "handling" the request also means returning a 
response, like a page. So for an access controller, you won't do this.
  
@@ -34, +34 @@

  {{{
  import java.io.IOException;
  
+ import org.apache.tapestry5.services.Dispatcher;
- import org.apache.tapestry.services.Request;
+ import org.apache.tapestry5.services.Request;
- import org.apache.tapestry.services.Response;
+ import org.apache.tapestry5.services.Response;
  
  public class AccessController implements Dispatcher {
        public boolean dispatch(Request request, Response response) throws 
IOException {
@@ -74, +75 @@

  
  == 3) Contribute Your Dispatcher to the MasterDispatcher ==
  Now we can inject our object using the id "!AccessController" into virtually 
anything. What we need to do now is contribute it to the !MasterDispatcher, so 
we'll inject it into the appropriate contribution method in our !AppModule. 
Before we do that, remember that the !MasterDispatcher is a chain of command, 
and that this chain is structured such that dispatchers are accessed in a 
specific order. This is good since we need to have our access controller 
positioned before certain dispatchers, like the page renderer, so we can 
effectively secure pages.
- So how do we do this? First you will know from the api (or source) that the 
!MasterDispatcher uses an 
[[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry/ioc/OrderedConfiguration.html|OrderedConfiguration]],
 and that such configurations allow constraints. These constraints allow you to 
add a new object before or after another, using the object's id and a simple 
syntax. You can look at the code for the syntax, but we know that we want our 
dispatcher to run before page requests are serviced. Page requests are handled 
by the dispatcher whose id is "!PageRender", so here is the contribution we 
need in our !AppModule:
+ So how do we do this? First you will know from the api (or source) that the 
!MasterDispatcher uses an 
[[http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry5/ioc/OrderedConfiguration.html|OrderedConfiguration]],
 and that such configurations allow constraints. These constraints allow you to 
add a new object before or after another, using the object's id and a simple 
syntax. You can look at the code for the syntax, but we know that we want our 
dispatcher to run before page requests are serviced. Page requests are handled 
by the dispatcher whose id is "!PageRender", so here is the contribution we 
need in our !AppModule:
  
  {{{
      public void contributeMasterDispatcher(OrderedConfiguration<Dispatcher> 
configuration,
@@ -90, +91 @@

   1. What to do when access is denied, and how to do it. There are 2 types of 
access violations: when a user is not logged in, and when a user is logged in 
but does not hold sufficient access privileges. The latter is easier, simply 
present a page telling the user they are not allowed to access what they 
requested. The former is a bit tricker since you'll want to redirect them to a 
login page. The access controller would have to know where to redirect to, and 
in both cases a redirect must be performed.
  
  For now I leave these to you. Any suggestions, corrections, or other 
furtherings on this document are most welcome. If you'd like to chat with me 
about this, you can find me in #tapestry on irc.freenode.net (chrislewis).
- ----
- CategoryCategory
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to