You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by Apache Wiki <wi...@apache.org> on 2007/06/30 07:47:15 UTC

[Tapestry Wiki] Update of "GeoffLongmanSandbox" by ErikVullings

Dear Wiki user,

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

The following page has been changed by ErikVullings:
http://wiki.apache.org/tapestry/GeoffLongmanSandbox

------------------------------------------------------------------------------
+ Describe GeoffLongmanSandbox here.
- I think there is a bug in T4 that is going to rear it's ugly head at some point.
- (and since wiki's are great for formatting things I'm going to lay out my case here and then point a JIRA issue to this page. Although JIRA will be the permanent record so I guess this will be an expanded discussion on the issue).
- 
- Depending on how a page is referenced in a link, Tapestry may or may not find the right page class. And, once it chooses the wrong page class, the app will probably break and stay broken until the servlet container is restarted.
- 
- ''If a page spec explicity specifies a class there is no problem, the problem arises when Tapestry goes searching for the class''
- 
- In fact it's worse than this. There could be the case where an app had two links, one in a form (not an HTML form!) that would cause Tapestry to find the correct class and one that would not. When this is possible then the stability of the application is suspect because all depends on whether the first user clicked the right link. If the first click by the first user was on the bad link, the whole app is broken until the servlet container is restarted.
- 
- Currently the [http://tapestry.apache.org/tapestry4/tapestry/apidocs/org/apache/tapestry/pageload/ComponentClassProvider.html ComponentClassProvider] uses a Hivemind chain to search for the page class. Passed into this chain is an instance of [http://tapestry.apache.org/tapestry4/tapestry/apidocs/org/apache/tapestry/pageload/ComponentClassProvider.html ComponentClassProviderContext] which contains:
-  * the page name
-  * the INamespace for the page
-  * the page specification
- 
- One member of the chain, [http://tapestry.apache.org/tapestry4/tapestry/apidocs/org/apache/tapestry/pageload/NamespaceClassSearchComponentClassProvider.html NamespaceClassSearchComponentClassProvider], gets a list of packages, say  {{{com.myfoo}}}, by checking a property in the Namespace and then checks each package for a class with a fully qualified name of the package with the page name appended. If the !NamespaceClassSearchComponentClassProvider does not locate a class it falls to other members of the chain and in most cases the resulting class would be {{{org.apache.tapestry.html.BasePage}}}.
- 
- The problem arises because the page name may be a path like{{{
- pages/MyPage
- }}}
- In the case above there is no problem, Tapestry would look for and probably find the class {{{com.myfoo.pages.MyPage}}}. However, Tapestry uses the same page name to locate the page spec (if one exists) and looks in various places like:{{{
- /
- /WEB-INF
- /WEB-INF/servletname
- }}}
- and there are several valid ways to reference a page in these places and each way would result in Tapestry looking for the page class in a different place. So there is the distinct possibility that Tapestry will __not__ find the page class intended by the developer and fall back to the !BasePage. Hence the app might break or not depending on who clicked what first.
- 
- === Example ===
- the following appears in test.application
- {{{
-   <meta key="org.apache.tapestry.page-class-packages" value="com.myfoo"/>  
-   <page name="Page" specification-path="/WEB-INF/pages/MyPage.page"/>
- }}}
- 
- and of course the files are located at {{{
- /WEB-INF/test.application
- /WEB-INF/pages/MyPage.page
- }}}
- 
- ''Sidenote: If a page is specless things can go wrong too. But, that's another story''
- 
- The class I've created for this page is {{{com.myfoo.pages.MyPage}}}.
- 
- Immediately I see 3 ways to reference !MyPage that will result in Tapestry sucessfully locating the specification and then go off looking for the page class:{{{
-  <span jwcid="@PageLink" page="Page"/>
-  <span jwcid="@PageLink" page="pages/MyPage"/>
-  <span jwcid="@PageLink" page="/WEB-INF/pages/Mypage"/>
- }}}
- Some of them links might not be pretty, but all are valid. We know that our class is {{{com.myfoo.pages.MyPage}}} and that the name used by !NamespaceClassSearchComponentClassProvider searched for will be, for each link, respectively:{{{
- com.myfoo.Page
- com.myfoo.pages.MyPage
- com.myfoo.WEB-INF.pages.MyPage
- }}}
- 
- HowardLewisShip: The third option is something I've never considered and would consider banning outright.  Also, I believe that page "Page" and page "pages/MyPage" are *distinct* pages, because they have distinct page names ("Page" vs. "pages/MyPage").  The expectation is that page "Page" will be class "com.myfoo.Page" and page "pages/MyPage" will be class "com.myfoo.pages.MyPage".
- 
- In all cases but the second, the page class Tapestry is searching for is not found and usually !BasePage ends up being used. And if {{{com.myfoo.pages.MyPage}}} has some properties that are refenced by an OGNL expression in the template, the page will break.
- 
- I think this problem also, in some cases, affects template lookup, but I have not delved into that. 
- 
- === The Fix ===
- It seems to me that the way this can be fixed so that Tapestry always looks for and finds {{{com.myfoo.pages.MyPage}}} is to do a bit more processing on the name passed in before handing things off to the !PageClassProvider. In every case above, Tapestry sucessfully locates the specification {{{/WEB-INF/pages/MyPage.page}}}. I think the fix would be to examine the path part of the page name and lop off the leading parts that would cause the class lookup to fail.
- 
- In particular I think that the locations Tapestry uses to find undeclared pages is a good place to start.
-  *Compare with the location of the namespace specification, if that is a prefix of the page name path, lop it off and __STOP__.
-  *Compare with {{{/WEB-INF/servletname}}} , if that is a prefix, lop it off and __STOP__.
-  *Compare with {{{/WEB-INF}}}, if that is a prefix, lop it off and __STOP__.
-  *If the above didn't result in a lopping, then the path is good.
- 
- HowardLewisShip: Still digesting this.
- 
- There would appear to be a special case. That is{{{
- <span jwcid="@PageLink" page="Page"/>
- }}}
- But it is not a special case, the lopping happens __after__ the specification has been resolved and thus the declared name does not come into the picture.{{{
- And I think that is a good thing. The declared name is much more likely to change than the name of the specification.
- }}}
- 
- but what about Specless pages? There is no spec! Well, really there is a spec. It's just that Tapestry create a __stand-in__ spec and that spec is given a location that can be used in the lopping too. Interestingly, the name given to the stand-in spec is the name in the path, so if one were to reference a specless page thus:{{{
- <span jwcid="@PageLink" page="pages/MySpeclessPage"/>
- }}}and Tapestry would go looking for {{{com.myfoo.pages.MySpeclessPage}}}, which is what I think users would expect.
- 
- There is a catch to that though, the location given to the stand-in spec is relative to the location of the namespace. In the example above our specless page's stand-in would have a location of {{{
- /WEB-INF/pages/MySpeclessPage.page
- }}}
- 
- Which looks good, if we take the lopping appraoch, the stand-in's location will work fine too.
- 
- === Implementing the Fix ===
- 
- I'm about 1/2 way through the fix. Since the lopping described above so closely parallels the logic in [http://jakarta.apache.org/tapestry/tapestry/apidocs/org/apache/tapestry/resolver/PageSpecificationResolverImpl.html PageSpecificationResolverImpl] and since it it true that once a page class has been found for a page there is no way to change it short of restarting the container, I think the whole kit and kaboodle should be moved out of !PageLoader and into !PageSpecificationResolverImpl.
- 
- __Out of time for today, will pick this up again tomorrow night__
- 
- last note. I have an example application that displays the broken behaviour I have described.
- 
  
  [http://static.flickr.com/29/54487210_e699a93095.jpg]
  

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org