Tutorials to .com

Tutorials to .com » Jsp » Tapestry-hivemind » Tapestry sub-page to identify and resolve issues

Tapestry sub-page to identify and resolve issues

Print View , by: iSee ,Total views: 16 ,Word Count: 4586 ,Date: Thu, 16 Apr 2009 Time: 9:15 PM

Sub-page for the Tapestry, I heard many of my friends have doubts about this. My own work, but also feel that too many pages in one directory (web / or web-inf /) under the terms for developers, is not conducive to management, but also seem very sick. Finally released the last two days time to focus on this issue.

Tapestry4 first find out the mechanism is template page, and then based on the template page where the directory to find the html file of the same name. /,page,Tapestrypagehtml(Tapestry4.0,htmlhtml)。 By default, page templates should be placed in the web / directory, web-inf / directory, or web-inf / [servletName] / directory, when found after page template, tapestry will go above and page directory to find the html file of the same name template (in Tapestry4.0 in, html templates html suffix is not necessarily the file).

In this case, we only will the project all the page templates and html templates in one directory, then if we want to put them in different pages directory to manage. Only through the application documents in the Tapestry defined page template where the path:

  /> "FirstPage" specification-path = "/ lilac / FirstPage.page" /> 

Note that FirstPage.page here is where the designated path. Rather than the corresponding FirstPage.html path where FirstPage.page.

If the page template html templates and not in the same directory:

As shown in red, Home.html located in web / lilac / home / directory, and Home.page located in web / web-inf / lilac / directory. They are completely not in the same directory, in accordance with the default search Tapestry4.0 is not Home.html documents. Felix Sun, after reminders, I come to provide an official solution, can be defined Home.page:

  /> "$ template" path = "context: / lilac / home / Home.html" /> 

OK, the above is the official, in order to achieve the distinction between official and my study, I will document the previous page you put together. If you just want to know the official sub-solutions. Then you can stop here. . The reason why I will "not satisfied" on the official sub-realization, because I think that there are defects, defective. Of course, I may be good enough, this is why we have a misunderstanding. If there are friends who can show me a better solution, very grateful:). . I had to explore the following two aspects:
(Of course, since it is to explore, may not be reasonable, and I did not complete the exploration)

If the html templates and page templates in a subdirectory is not the same, I will try another solution:

I tried different solutions with the official approach, by default Tapestry4.0 Reconstruction hivemind achieve:

  ?> "1.0" encoding = "gb2312"?>   package = "com.tapestry4.test" > "MyTapestry" version = "1.0.0" package = "com.tapestry4.test">       "tapestry.l10n.ResourceLocalizers">           /> "myResource" object = "instance: MyResourceLocalizer" />     
   com.tapestry4.test; package com.tapestry4.test;    java.util.Locale; import java.util.Locale;    org.apache.hivemind.Resource; import org.apache.hivemind.Resource;    org.apache.tapestry.l10n.ResourceLocalizer; import org.apache.tapestry.l10n.ResourceLocalizer;    class MyResourceLocalizer implements  ResourceLocalizer { public class MyResourceLocalizer implements ResourceLocalizer (            Resource findLocalization(Resource rootResource, Locale locale) { public Resource findLocalization (Resource rootResource, Locale locale) (                    (rootResource.getPath().equals( "/Home.html" )) { if (rootResource.getPath (). equals ( "/ Home.html")) (                           rootResource = rootResource                                           ); . getRelativeResource ( "lilac / home / Home.html");                   )                    rootResource.getLocalization(locale); return rootResource.getLocalization (locale);           )   ) 

Org.apache.tapestry.l10n in the Tapestry4.0 package (this is the rc-1 until a new packet) DefaultResourceLocalizer under a category, where I was to rewrite the class through the Hivemind.

   org.apache.tapestry.l10n; package org.apache.tapestry.l10n;    java.util.Locale; import java.util.Locale;    org.apache.hivemind.Resource; import org.apache.hivemind.Resource;   / **    * Default implementation of (@ link org.apache.tapestry.l10n.ResourceLocalizer) that leverages the    * Localization rules built into    * (@ Link org.apache.hivemind.Resource # getLocalization (java.util.Locale)).    *    * @ Author Howard M. Lewis Ship    * @ Since 4.0    * /    class DefaultResourceLocalizer implements  ResourceLocalizer public class DefaultResourceLocalizer implements ResourceLocalizer   (       / **        * Invokes (@ link Resource # getLocalization (java.util.Locale)).        * /        Resource findLocalization(Resource rootResource, Locale locale) public Resource findLocalization (Resource rootResource, Locale locale)       (            rootResource.getLocalization(locale); return rootResource.getLocalization (locale);       )   ) 

DefaultResourceLocalizer official from the Tapestry group, as a result of Home.html with Home.page not in the same directory, so rootResource.getLocalization (locale) will return null, then Tapestry will error. Then, when I rewrite MyResourceLocalizer, once I found Tapestry looking Home.html document, I will set up the new address into Home.html:

   (rootResource.getPath().equals( "/Home.html" )) { if (rootResource.getPath (). equals ( "/ Home.html")) (       ); rootResource = rootResource.getRelativeResource ( "lilac / home / Home.html");   ) 

Of course, if directly used to do a little wrong to judge, but the whole idea of this is the case, we can add their own MyResourceLocalizer method is to sum up rootResource.getRelativeResource () method to set up a new path. Concrete realization of the details, we will not discussed here.

Sub-page to the evils of Tapestry

Tapestry pages to sub-contractors, there will be a matter of opinion disadvantages. I say "a matter of opinion" because maybe some friends of ours do not think this is a disadvantages.

Once, after sub-Tapestry pages, html template images, flash and other resources in the path, such as in the dreamware such as "WYSIWYG" tool, in order to facilitate the art editor, for example, placed in front of our web / lilac / directory FirstPage . html:

Picture is placed in the web / lilac / images / directory, then in Dreamware art, you can directly modify the html template:

But when we actually run the project, in the FirstPage page, this problem occurs:

Tapestry will be placed on the page Run, and the true path picture Under. Therefore, in order to project the correct image is running, art in Dreamware can not see on the map; To see a map art, then the project run-time image on the display do not come out (of the art development team, we do not Tapestry, because art on page should only art alone, this is a team division). In other words, Dreamware that FirstPage.html in the web / lilac / directory, and the actual run-time items, FirstPage.html but at the web / directory. . In addition, even if a project has been issued may at any time, there are some maintenance issues. Art can not see pictures, certainly very troublesome to maintain. Of course, you can use an extreme approach, html template for all the static images, flash all use Tapestry for the output of the asset, but an html imagine there may be hundreds of static pictures, Tapestry calls brought about by hundreds of asset the performance of consumption, as well as hundreds of developers to the definition of the tremendous asset the workload. I think that is very unrealistic.

So, if we can run FirstPage page url from Read , We can solve this problem. Which is one of the sub-directory / lilac / we can not write to die, because html template may be placed in different directory. So I do the following to explore:

First, the modified web.xml

          lilac           org.apache.tapestry.ApplicationServlet           lilac           * / app 

Secondly, org.apache.tapestry.services.impl.LinkFactoryImpl rewrite hivemind categories:

Quote Address: http://www.javaeye.com/pages/viewpage.action?pageId=680

  ?> "1.0" encoding = "gb2312"?>   "tapestry.url.LinkFactory">                                     "MyLinkFactoryImpl">                                   /> "dataSqueezer" value = "infrastructure: dataSqueezer" />                                   /> "contributions" configuration-id = "tapestry.url.ServiceEncoders" />                                   /> "servletPath" value = "app-property: org.apache.tapestry.servlet-path" />                                   /> "contextPath" value = "infrastructure: contextPath" />                                   /> "request" value = "infrastructure: request" />                                   /> "requestCycle" value = "infrastructure: requestCycle" />                                   "persistenceStrategySource"                                           /> service-id = "tapestry.persist.PropertyPersistenceStrategySource" />                                    /> "localizer" value = "infrastructure: resourceLocalizer" />                                   
   com.tapestry4.test; package com.tapestry4.test;    java.util.Iterator; import java.util.Iterator;    java.util.List; import java.util.List;    java.util.Locale; import java.util.Locale;    java.util.Map; import java.util.Map;    org.apache.commons.codec.net.URLCodec; import org.apache.commons.codec.net.URLCodec;    org.apache.hivemind.ApplicationRuntimeException; import org.apache.hivemind.ApplicationRuntimeException;    org.apache.hivemind.ErrorLog; import org.apache.hivemind.ErrorLog;    org.apache.hivemind.Resource; import org.apache.hivemind.Resource;    org.apache.hivemind.order.Orderer; import org.apache.hivemind.order.Orderer;    org.apache.hivemind.util.Defense; import org.apache.hivemind.util.Defense;    org.apache.tapestry.IEngine; import org.apache.tapestry.IEngine;    org.apache.tapestry.IPage; import org.apache.tapestry.IPage;    org.apache.tapestry.IRequestCycle; import org.apache.tapestry.IRequestCycle;    org.apache.tapestry.Tapestry; import org.apache.tapestry.Tapestry;    org.apache.tapestry.engine.EngineServiceLink; import org.apache.tapestry.engine.EngineServiceLink;    org.apache.tapestry.engine.IEngineService; import org.apache.tapestry.engine.IEngineService;    org.apache.tapestry.engine.ILink; import org.apache.tapestry.engine.ILink;    org.apache.tapestry.engine.ServiceEncoder; import org.apache.tapestry.engine.ServiceEncoder;    org.apache.tapestry.engine.ServiceEncoding; import org.apache.tapestry.engine.ServiceEncoding;    org.apache.tapestry.engine.ServiceEncodingImpl; import org.apache.tapestry.engine.ServiceEncodingImpl;    org.apache.tapestry.l10n.ResourceLocalizer; import org.apache.tapestry.l10n.ResourceLocalizer;    org.apache.tapestry.record.PropertyPersistenceStrategySource; import org.apache.tapestry.record.PropertyPersistenceStrategySource;    org.apache.tapestry.services.DataSqueezer; import org.apache.tapestry.services.DataSqueezer;    org.apache.tapestry.services.LinkFactory; import org.apache.tapestry.services.LinkFactory;    org.apache.tapestry.services.ServiceConstants; import org.apache.tapestry.services.ServiceConstants;    org.apache.tapestry.services.impl.ServiceEncoderContribution; import org.apache.tapestry.services.impl.ServiceEncoderContribution;    org.apache.tapestry.spec.IComponentSpecification; import org.apache.tapestry.spec.IComponentSpecification;    org.apache.tapestry.web.WebRequest; import org.apache.tapestry.web.WebRequest;    class MyLinkFactoryImpl implements  LinkFactory { public class MyLinkFactoryImpl implements LinkFactory (            DataSqueezer _dataSqueezer; private DataSqueezer _dataSqueezer;            ErrorLog _errorLog; private ErrorLog _errorLog;            List _contributions; private List _contributions;            ServiceEncoder[] _encoders; private ServiceEncoder [] _encoders;           String  _contextPath; private String _contextPath;           String  _servletPath; private String _servletPath;           Object [] EMPTY = new Object [0]; private final Object [] EMPTY = new Object [0];            URLCodec _codec = new  URLCodec(); private URLCodec _codec = new URLCodec ();            WebRequest _request; private WebRequest _request;            IRequestCycle _requestCycle; private IRequestCycle _requestCycle;            PropertyPersistenceStrategySource _persistenceStrategySource; private PropertyPersistenceStrategySource _persistenceStrategySource;            ResourceLocalizer localizer; private ResourceLocalizer localizer;            void initializeService() { public void initializeService () (                    Orderer(_errorLog, "encoder" ); Orderer orderer = new Orderer (_errorLog, "encoder");                   Iterator i = _contributions.iterator ();                    (i.hasNext()) { while (i.hasNext ()) (                           ServiceEncoderContribution c = (ServiceEncoderContribution) i                                           . next ();                           orderer.add (c, c.getId (), c.getAfter (), c.getBefore ());                   )                   List ordered = orderer.getOrderedObjects ();                    count = ordered.size(); int count = ordered.size ();                    ServiceEncoder[count]; _encoders = new ServiceEncoder [count];                    ( int  j = 0; j < count; j++) { for (int j = 0; j <count; j + +) (                           ServiceEncoderContribution C++ = (ServiceEncoderContribution) ordered                                           . get (j);                           _encoders [j] = c.getEncoder ();                   )           )            ILink constructLink(IEngineService service, boolean  post, public ILink constructLink (IEngineService service, boolean post,                            stateful) { Map parameters, boolean stateful) (                   finalizeParameters (service, parameters);                   IEngine engine = _requestCycle.getEngine ();                   ServiceEncoding serviceEncoding = createServiceEncoding (parameters);                    (stateful) if (stateful)                           _persistenceStrategySource.addParametersForPersistentProperties (                                           serviceEncoding, post);                   / / Rewrite PageLink and ExternalLink generated URL, the URL so that they generate a html template on which the path of the directory.    path = ""; String path = "";                    serviceName = ( String )parameters.get(ServiceConstants.SERVICE); String serviceName = (String) parameters.get (ServiceConstants.SERVICE);                   (serviceName.equals(Tapestry.EXTERNAL_SERVICE)||serviceName.equals(Tapestry.PAGE_SERVICE)) { if (serviceName.equals (Tapestry.EXTERNAL_SERVICE) | | serviceName.equals (Tapestry.PAGE_SERVICE)) (                            pageName = ( String ) parameters.get(ServiceConstants.PAGE); String pageName = (String) parameters.get (ServiceConstants.PAGE);                            (pageName != null ) { if (pageName! = null) (                                   IPage page = _requestCycle.getPage (pageName);                                   IComponentSpecification specification = page.getSpecification ();                                   Resource baseLocation = specification.getSpecificationLocation ();                                   Locale locale = _requestCycle.getEngine (). GetLocale ();                                   Resource localizedLocation = localizer.findLocalization (baseLocation, locale);                                    index = localizedLocation.getPath().indexOf(pageName); int index = localizedLocation.getPath (). indexOf (pageName);                                    (index > 0) { if (index> 0) (                                           path = localizedLocation.getPath (). substring (0, index - 1);                                   )                           )                   )                    fullServletPath = path + _contextPath String fullServletPath = path + _contextPath                                   + ServiceEncoding.getServletPath ();                    EngineServiceLink(_requestCycle, fullServletPath, engine return new EngineServiceLink (_requestCycle, fullServletPath, engine                                   . getOutputEncoding (), _codec, _request, parameters, stateful);           )           ) @ SuppressWarnings ( "unchecked")            void finalizeParameters(IEngineService service, Map parameters) { protected void finalizeParameters (IEngineService service, Map parameters) (                   ); Defense.notNull (service, "service");                   ); Defense.notNull (parameters, "parameters");                    serviceName = service.getName(); String serviceName = service.getName ();                    (serviceName == null ) if (serviceName == null)                            ApplicationRuntimeException( "service-name-is- null " ); throw new ApplicationRuntimeException ( "service-name-is-null");                   parameters.put (ServiceConstants.SERVICE, serviceName);                   squeezeServiceParameters (parameters);           )            ServiceEncoder[] getServiceEncoders() { public ServiceEncoder [] getServiceEncoders () (                    _encoders; return _encoders;           )            ServiceEncoding createServiceEncoding(Map parameters) { private ServiceEncoding createServiceEncoding (Map parameters) (                    ServiceEncodingImpl(_servletPath, ServiceEncodingImpl result = new ServiceEncodingImpl (_servletPath,                                   parameters);                    ( int  i = 0; i < _encoders.length; i++) { for (int i = 0; i <_encoders.length; i + +) (                           _encoders [i]. encode (result);                            (result.isModified()) if (result.isModified ())                                   ; break;                   )                    result; return result;           )           ) @ SuppressWarnings ( "unchecked")            void squeezeServiceParameters(Map parameters) { protected void squeezeServiceParameters (Map parameters) (                   [] serviceParameters = ( Object []) parameters Object [] serviceParameters = (Object []) parameters                                   . get (ServiceConstants.PARAMETER);                    (serviceParameters == null ) if (serviceParameters == null)                           ; return;                   [] squeezed = squeeze(serviceParameters); String [] squeezed = squeeze (serviceParameters);                   parameters.put (ServiceConstants.PARAMETER, squeezed);           )           Object [] extractListenerParameters(IRequestCycle cycle) { public Object [] extractListenerParameters (IRequestCycle cycle) (                   [] squeezed = cycle.getParameters(ServiceConstants.PARAMETER); String [] squeezed = cycle.getParameters (ServiceConstants.PARAMETER);                    (Tapestry.size(squeezed) == 0) if (Tapestry.size (squeezed) == 0)                            EMPTY; return EMPTY;                    { try (                            _dataSqueezer.unsqueeze(squeezed); return _dataSqueezer.unsqueeze (squeezed);                    (Exception ex) { ) Catch (Exception ex) (                            ApplicationRuntimeException(ex); throw new ApplicationRuntimeException (ex);                   )           )           String [] squeeze( Object [] input) { private String [] squeeze (Object [] input) (                    { try (                            _dataSqueezer.squeeze(input); return _dataSqueezer.squeeze (input);                    (Exception ex) { ) Catch (Exception ex) (                            ApplicationRuntimeException(ex); throw new ApplicationRuntimeException (ex);                   )           )            void setDataSqueezer(DataSqueezer dataSqueezer) { public void setDataSqueezer (DataSqueezer dataSqueezer) (                   _dataSqueezer = dataSqueezer;           )            void setContributions(List contributions) { public void setContributions (List contributions) (                   _contributions = contributions;           )            void setErrorLog(ErrorLog errorLog) { public void setErrorLog (ErrorLog errorLog) (                   _errorLog = errorLog;           )            void setServletPath( String  servletPath) { public void setServletPath (String servletPath) (                   _servletPath = servletPath;           )            void setContextPath( String  contextPath) { public void setContextPath (String contextPath) (                   _contextPath = contextPath;           )            void setRequest(WebRequest request) { public void setRequest (WebRequest request) (                   _request = request;           )            void setPersistenceStrategySource( public void setPersistenceStrategySource (                           PropertyPersistenceStrategySource persistenceStrategySource) (                   _persistenceStrategySource = persistenceStrategySource;           )            void setRequestCycle(IRequestCycle requestCycle) { public void setRequestCycle (IRequestCycle requestCycle) (                   _requestCycle = requestCycle;           )            ResourceLocalizer getLocalizer() { public ResourceLocalizer getLocalizer () (                    localizer; return localizer;           )            void setLocalizer(ResourceLocalizer localizer) { public void setLocalizer (ResourceLocalizer localizer) (                   .localizer = localizer; this. localizer = localizer;           )   ) 

Through this rewriting MyLinkFactoryImpl, will PageLink and two ExternalLink generated url in html template which contains the path of the directory. Even with the page template html template directory is not the same (of course, if the page template html templates and not in the same directory, on the need to use the official page template in the definition of $ Tamplate, or the realization that I mentioned earlier MyResourceLocalizer).

However, this does not end, because we in Form submitted, DirectLink, ActionLink Jump time, but also need to add url Jump html page where the directory path template. For this issue, I have not yet thought about the right approach, because ActionService generated DirectService and only the url contains the path where the page, such as: = $ DirectLink & page = Home & service = direct The URL of the DirectLink, described 1) the DirectLink component of the page where the "page = Home"; 2) the DirectLink component in the Home page of the ID "component = $ DirectLink"; 3) The components DirectLink call service "service = direct". Who genuinely need a Jump of the page only in its method of operation of the corresponding monitor, would know. If, after running in the monitor method, and then add the URL to the blind sub-directory path: = $ DirectLink & page = Home & service = direct . So will only lead to, it will trigger the existence of repeat and repeat DirectService methods trigger monitor. And any use of the DirectLink component DirectService and Form components, as well as the URL generated by ActionService there are such problems.

If you have any idea of a friend, and I very much welcome to explore.

One solution: The DirectService and the URL generated by ActionService amended to PageService the URL or ExternalService

First of all, it was not for my sub-directory of the creation of a separate study. Long time ago, in Tapestry3.0, there is the use of Form submission, refresh the page to submit the issue of duplication. This is because the URL generated DirectService caused. In order to address the issue of duplicate submission, the approach is to DirectServcie the URL generated by the ExternalService amended to read URL. Yesterday, I happen to think, the use of this approach can solve the sub-directory on the issue, although the Form or URL generated DirectLink did not provide the next page Jump to the page name, but once their ExternalLink or URL into a URL of PageLink after, URL of the page associated with the name, will be reconstructed by analytic MyLinkFactoryImpl that URL to insert in the corresponding sub-directory. See also: solution to refresh the page to submit a result of repeated Form trigger monitoring methods .

With regard to "transfer URL" to resolve the issue of sub-directories, my personal view:


  • Solve the sub-directory of resources brought about by the path of confusion picture. A couple of days ago, our art MM angry because in the sub-page, she can not see pictures, if she had seen pictures, the page can not see the actual plans to run again. like us who, of course, have to do something for the artists considered MM ;
  • Refresh the page to avoid duplicate submission of cause;


  • Discarded DirectService methods to monitor the way value. It said, can no longer use the setter methods in the value of listening to the next instance of a page;
  • DirectService discarded the effectiveness of the session;
  • Due to URL length is limited (1k), Therefore, when passing a large number of strings, ExternalService there will be problems in the URL. Of course, this problem can be solved: first, the monitor is available, we can still call methods in monitoring the completion of our Business Logic Tier after a lot of work, and then down a small number of parameters of transmission page; the second, if indeed there are need to transfer a large number of parameters, you can transfer the entire VO object, or a lot of string wrapped in a Map, List, such as collection of objects, and then transfer. This is because the Tapestry object passing through the URL. In fact, URL in the portable object identification only, the identification string is generated by the Tapestry of DataSqueezer, when access to the next page, Tapestry string based on the logo to find the cache in the framework of the corresponding object.

Are both advantages and disadvantages of anything, only look at each of the special circumstances under which a trade-off.

tapestry & hivemind Articles

Can't Find What You're Looking For?

Rating: Not yet rated


No comments posted.