hi @ all, what jakob is talking about makes a lot of sense to me.
@jakob: please don't fork it. imo we should continue with the approach started by jakob + the addition mentioned by martin. after finishing that we can think about further improvements (if needed at all). @leo: do you feel we need a vote about it? regards, gerhard 2011/6/30, Jakob Korherr <[email protected]>: > Hm, you're not getting it. This > >> To do it correctly we need to detect if this is a servlet 3.0 >> container and do the necessary stuff, but we need to test what happen >> if a 2.5 or 2.4 web.xml file is deployed on a 3.0 container. >> Additionally, we need to take care about do not call 3.0 code in 2.5 >> servlet container. This will not be an easy trick, I'm sure of it. > > was the idea at that point, but it wasn't done, b/c there was no time > for it at that point. > > Unfortunately we two don't seem to get along here. Each one of us > seems to have a very different idea of how this should be done and > frankly I am tired of this discussion. Thus I created a fork of my > initial resource-handler implementation (before you started > committing) at a different code-hoster. This way everyone can > implement what seems best for him/his users. > > Regards, > Jakob > > 2011/6/30 Leonardo Uribe <[email protected]>: >> 2011/6/30 Jakob Korherr <[email protected]>: >>>> [...] The new alternative proposed is similar. >>> >>> This alternative is not "new"! My first version of the >>> AdvancedResourceHandler (before you started committing) already did >>> exactly this! (However, assuming /faces/* as mapping if the page was >>> accessed via suffix mapping, but making it configurable would have >>> done the job too.) >> >> It is new, because the idea is detect a valid prefix mapping when a >> suffix mapping request is sent. The code inside >> AdvancedResourceHandler didn't do that, it's more, assume something >> about the environment it is not something good, its like do a bet. The >> filter solution provide an algorithm to deal with all possible >> configurations, and note the new strategy can be integrated with the >> filter solution without any problem (i'm not thinking on the spec, >> instead I'm thinking that the module is on myfaces commons and we can >> do whatever we want). >> >> To do it correctly we need to detect if this is a servlet 3.0 >> container and do the necessary stuff, but we need to test what happen >> if a 2.5 or 2.4 web.xml file is deployed on a 3.0 container. >> Additionally, we need to take care about do not call 3.0 code in 2.5 >> servlet container. This will not be an easy trick, I'm sure of it. >> >> regards, >> Leonardo >> >>> >>> Regards, >>> Jakbo >>> >>> 2011/6/30 Leonardo Uribe <[email protected]>: >>>> Hi Jakob >>>> >>>> 2011/6/30 Jakob Korherr <[email protected]>: >>>>> Hi Martin, >>>>> >>>>> Thank you so much for your mail! >>>>> >>>>> This is exactly my point of view about the ResourceHandler. However, >>>>> Leonardo in I kinda got into a "fight" about it and unfortunately, I >>>>> do not have time for that right now! >>>> >>>> For me this is just a work that we need to do. Don't get me wrong. My >>>> intention is build this stuff correctly, and if I see a problem, I'll >>>> discuss it and fix it. In fact, I'm taking concrete actions to add the >>>> features I proposed into the module, and change some other things that >>>> just needs more work. >>>> >>>>> >>>>> Leonardo, please reconsider my reasoning from the previous mails of >>>>> this discussion. >>>>> >>>> >>>> Now we have found an alternative to get rid the filter stuff and use >>>> only FacesServlet. >>>> >>>>>>the resource url should then always be generated with the prefix >>>>>>mapping - how can this lead to inconsistencies? >>>>> >>>>> I also don't think there could be inconsistencies. However, Leonardo >>>>> thinks so, but unfortunately he could not give an example. >>>>> >>>> >>>> I gave you the use case. Look this fragment on a previous mail: >>>> >>>> "... If a page is rendered using suffix mapping, resource paths will >>>> use that and not prefix mapping, because faces mapping is derived from >>>> the request path ..." >>>> >>>> The filter did solve the problem, because it provided a way to detect >>>> itself and generate a valid prefixed url. The new alternative proposed >>>> is similar. >>>> >>>> regards, >>>> >>>> Leonardo Uribe >>>> >>>>> Regards, >>>>> Jakob >>>>> >>>>> 2011/6/30 Martin Marinschek <[email protected]>: >>>>>> Hi guys, >>>>>> >>>>>> let me weigh in on the filter question: please, no filter! >>>>>> >>>>>> @prefix suffix mappings: you can get the registered mappings >>>>>> >>>>>> in previous servlet versions: parsing the web.xml >>>>>> in servlet 3.0: via the API >>>>>> http://download.oracle.com/javaee/6/api/javax/servlet/ServletRegistration.html >>>>>> >>>>>> the resource url should then always be generated with the prefix >>>>>> mapping - how can this lead to inconsistencies? >>>>>> >>>>>> best regards, >>>>>> >>>>>> Martin >>>>>> >>>>>> On Thu, Jun 23, 2011 at 11:54 PM, Leonardo Uribe <[email protected]> >>>>>> wrote: >>>>>>> Hi >>>>>>> >>>>>>> In the last days this enhancements were commited: >>>>>>> >>>>>>> ------------------------------------------------------------------------------ >>>>>>> >>>>>>> Added GZIP compression to ExtendedResourceHandler and these params: >>>>>>> >>>>>>> /** >>>>>>> * Enable or disable gzip compressions for resources served by >>>>>>> this extended resource handler. By default is disabled (false). >>>>>>> */ >>>>>>> @JSFWebConfigParam(defaultValue="false") >>>>>>> public static final String INIT_PARAM_GZIP_RESOURCES_ENABLED = >>>>>>> "org.apache.myfaces.commons.GZIP_RESOURCES_ENABLED"; >>>>>>> >>>>>>> /** >>>>>>> * Indicate the suffix used to recognize resources that should be >>>>>>> compressed. By default is ".css .js". >>>>>>> */ >>>>>>> @JSFWebConfigParam(defaultValue=".css, .js") >>>>>>> public static final String INIT_PARAM_GZIP_RESOURCES_SUFFIX = >>>>>>> "org.apache.myfaces.commons.GZIP_RESOURCES_SUFFIX"; >>>>>>> public static final String >>>>>>> INIT_PARAM_GZIP_RESOURCES_EXTENSIONS_DEFAULT = ".css .js"; >>>>>>> >>>>>>> /** >>>>>>> * Indicate if gzipped files are stored on a temporal directory to >>>>>>> serve them later. By default is true. If this is >>>>>>> * disable, the files are compressed when they are served. >>>>>>> */ >>>>>>> @JSFWebConfigParam(defaultValue="true") >>>>>>> public static final String INIT_PARAM_CACHE_DISK_GZIP_RESOURCES = >>>>>>> "org.apache.myfaces.commons.CACHE_DISK_GZIP_RESOURCES"; >>>>>>> >>>>>>> by default compression is set to false. It could be good to enable >>>>>>> compression only on files bigger than some specified lenght, to allow >>>>>>> finer tuning. >>>>>>> >>>>>>> ------------------------------------------------------------------------------ >>>>>>> >>>>>>> >>>>>>> and these enhancements: >>>>>>> >>>>>>> >>>>>>> ------------------------------------------------------------------------------ >>>>>>> >>>>>>> Added new scanning and parsing of myfaces-resources-config.xml files. >>>>>>> It was added this param: >>>>>>> >>>>>>> /** >>>>>>> * This param allow to override the default strategy to locate >>>>>>> myfaces-resources-config.xml files, that will be parsed later. In >>>>>>> this >>>>>>> way >>>>>>> * it is possible to include new source locations or handle cases >>>>>>> like OSGi specific setup. >>>>>>> */ >>>>>>> @JSFWebConfigParam >>>>>>> public static final String >>>>>>> INIT_PARAM_EXTENDED_RESOURCE_HANDLER_CONFIG_URL_PROVIDER = >>>>>>> "org.apache.myfaces.commons.EXTENDED_RESOURCE_HANDLER_CONFIG_URL_PROVIDER"; >>>>>>> >>>>>>> I think just a param that instantiate a class implementing >>>>>>> MyFacesResourceHandlerUrlProvider is enough. The default algorithm >>>>>>> loook on classpath for META-INF/myfaces-resources-config.xml and on >>>>>>> servlet context for WEB-INF/myfaces-resources-config.xml files. >>>>>>> >>>>>>> myfaces-resources-config.xml files can be used with these options: >>>>>>> >>>>>>> <?xml version="1.0" encoding="UTF-8"?> >>>>>>> <myfaces-resources-config> >>>>>>> <!-- Mark this library to be handled by Extended Resource Handler >>>>>>> --> >>>>>>> <library> >>>>>>> <library-name>libraryA</library-name> >>>>>>> </library> >>>>>>> >>>>>>> <!-- Indicate this library has another name, so if libraryC is >>>>>>> used, >>>>>>> resources should be redirected to libraryC1 --> >>>>>>> <library> >>>>>>> <library-name>libraryC</library-name> >>>>>>> <redirect-name>libraryC1</redirect-name> >>>>>>> </library> >>>>>>> >>>>>>> <!-- Allow to customize the request path generated, to do things >>>>>>> like >>>>>>> take library resources from a Content Delivery Network (CDN) or >>>>>>> just >>>>>>> take it directly from an specified location. Note it is >>>>>>> responsibility >>>>>>> of the developer to configure it properly, and the resources >>>>>>> should >>>>>>> exists locally under the library name selected. --> >>>>>>> <library> >>>>>>> <library-name>libraryB</library-name> >>>>>>> >>>>>>> <request-path>http://someaddress.com/alternatePath/#{resourceName}</request-path> >>>>>>> <!-- This example shows the variables that can be called >>>>>>> inside the expression to construct the request map >>>>>>> <request-path>#{extensionMapping ? '' : >>>>>>> mapping}/javax.faces.resource/$/#{localePrefix}/#{libraryName}/#{resourceName}#{extensionMapping >>>>>>> ? mapping : ''}</request-path> >>>>>>> --> >>>>>>> </library> >>>>>>> >>>>>>> </myfaces-resources-config> >>>>>>> >>>>>>> All libraries referenced here will be handled by the extended >>>>>>> ResourceHandler. Additionally, there is an option to redirect a >>>>>>> library name into another, to deal with possible conflicts between >>>>>>> resources loaded, specially javascript libraries. And finally there >>>>>>> is >>>>>>> an option to override the request-path with an EL expression, so if >>>>>>> you have a library with some static resources it is easy to construct >>>>>>> an url to load them from a Content Delivery Network (CDN) or just >>>>>>> from >>>>>>> some specified path. The only thing you should note is the library >>>>>>> should exists locally under the library name, to detect when a >>>>>>> resource can be resolved or not. >>>>>>> >>>>>>> ------------------------------------------------------------------------------ >>>>>>> >>>>>>> I have not tested it fully, but in my opinion it looks good. I has >>>>>>> the >>>>>>> best of the previous AdvancedResourceHandler with some new valuable >>>>>>> features proposed. >>>>>>> >>>>>>> If no objections I'll remove the previous code, since it was >>>>>>> integrated on the alternate solution. >>>>>>> >>>>>>> Suggestions and tomatoes are welcome >>>>>>> >>>>>>> Leonardo Uribe >>>>>>> >>>>>>> 2011/6/14 Leonardo Uribe <[email protected]>: >>>>>>>> Hi Jakob >>>>>>>> >>>>>>>> 2011/6/14 Jakob Korherr <[email protected]>: >>>>>>>>> Hi Leonardo, >>>>>>>>> >>>>>>>>>>Because set prefix and suffix mapping for the same webapp could >>>>>>>>>> lead >>>>>>>>>>to inconsistencies. >>>>>>>>> >>>>>>>>> Which inconsistencies exactly? Please give an example, I can't >>>>>>>>> really >>>>>>>>> think of any! >>>>>>>>> >>>>>>>> >>>>>>>> Let's take a look to AdvanceResource.getRequestPath: >>>>>>>> >>>>>>>> public String getRequestPath() >>>>>>>> { >>>>>>>> FacesContext facesContext = >>>>>>>> FacesContext.getCurrentInstance(); >>>>>>>> StringBuilder path = new StringBuilder(); >>>>>>>> >>>>>>>> path.append(ResourceUtils.getFacesServletPrefix(facesContext)); >>>>>>>> ..... >>>>>>>> >>>>>>>> Now look on getFacesServletPrefix: >>>>>>>> >>>>>>>> public static String getFacesServletPrefix(FacesContext >>>>>>>> facesContext) >>>>>>>> { >>>>>>>> ExternalContext externalContext = >>>>>>>> facesContext.getExternalContext(); >>>>>>>> Map<String, Object> applicationMap = >>>>>>>> externalContext.getApplicationMap(); >>>>>>>> >>>>>>>> // check if already cached >>>>>>>> String prefix = (String) >>>>>>>> applicationMap.get(FACES_SERVLET_PREFIX_KEY); >>>>>>>> if (prefix == null) >>>>>>>> { >>>>>>>> // try to extract it from current request >>>>>>>> prefix = getFacesServletPrefixMapping(facesContext); >>>>>>>> .... >>>>>>>> >>>>>>>> public static String getFacesServletPrefixMapping(FacesContext >>>>>>>> facesContext) >>>>>>>> { >>>>>>>> ExternalContext externalContext = >>>>>>>> facesContext.getExternalContext(); >>>>>>>> >>>>>>>> String pathInfo = externalContext.getRequestPathInfo(); >>>>>>>> String servletPath = externalContext.getRequestServletPath(); >>>>>>>> >>>>>>>> if (pathInfo != null) >>>>>>>> { >>>>>>>> return servletPath; >>>>>>>> } >>>>>>>> else >>>>>>>> { >>>>>>>> // In the case of extension mapping, no "extra path" is >>>>>>>> available. >>>>>>>> // Still it's possible that prefix-based mapping has been >>>>>>>> used. >>>>>>>> // Actually, if there was an exact match no "extra path" >>>>>>>> // is available (e.g. if the url-pattern is "/faces/*" >>>>>>>> // and the request-uri is "/context/faces"). >>>>>>>> int slashPos = servletPath.lastIndexOf('/'); >>>>>>>> int extensionPos = servletPath.lastIndexOf('.'); >>>>>>>> if (extensionPos > -1 && extensionPos > slashPos) >>>>>>>> { >>>>>>>> // we are only interested in the prefix mapping >>>>>>>> return null; >>>>>>>> } >>>>>>>> else >>>>>>>> { >>>>>>>> // There is no extension in the given servletPath and >>>>>>>> therefore >>>>>>>> // we assume that it's an exact match using >>>>>>>> prefix-based mapping. >>>>>>>> return servletPath; >>>>>>>> } >>>>>>>> } >>>>>>>> } >>>>>>>> >>>>>>>> The code takes pathInfo/servletPath information and prepend it to >>>>>>>> the >>>>>>>> beggining. The first bug is the code prepend the extension when >>>>>>>> suffix >>>>>>>> mapping is used!. But look the mapping is saved on the application >>>>>>>> map. So on further request, the mapping is retrieved from >>>>>>>> application >>>>>>>> map, so if the first request is suffix mapping, all later resource >>>>>>>> request paths will be generated wrong, even if prefix mapping is >>>>>>>> used. >>>>>>>> >>>>>>>> The problem is to know if prefix mapping is used you should parse >>>>>>>> web.xml file, but that's wrong, because in servlet 3.0 spec you >>>>>>>> don't >>>>>>>> necessary have that file (web fragment?). In conclusion there is no >>>>>>>> way to "detect" and generate the mapping correctly. >>>>>>>> >>>>>>>> The nice part about the filter is you can put some code to detect >>>>>>>> automatically if the filter is registered or not and act according. >>>>>>>> This is the param: >>>>>>>> >>>>>>>> /** >>>>>>>> * Indicate if this filter is being used to process request. It >>>>>>>> works in three modes: >>>>>>>> * >>>>>>>> * <ul> >>>>>>>> * <li>true: assume the filter is correctly setup.</li> >>>>>>>> * <li>check: check if the filter has been setup and if that so, >>>>>>>> use it. Otherwise, it uses FacesServlet (use prefix mapping to make >>>>>>>> all features work).</li> >>>>>>>> * <li>false: filter is not used at all.</li> >>>>>>>> * </ul> >>>>>>>> */ >>>>>>>> @JSFWebConfigParam(defaultValue="check", expectedValues="true, >>>>>>>> false, check") >>>>>>>> public static final String >>>>>>>> INIT_PARAM_USE_EXTENDED_RESOURCE_FILTER >>>>>>>> = "org.apache.myfaces.commons.USE_EXTENDED_RESOURCE_FILTER"; >>>>>>>> public static final String >>>>>>>> INIT_PARAM_USE_EXTENDED_RESOURCE_FILTER_DEFAULT = "check"; >>>>>>>> >>>>>>>> In this way, there will not be inconsistencies, because we have the >>>>>>>> three options: >>>>>>>> >>>>>>>> - If prefix mapping is used -> prepend the prefix >>>>>>>> - If suffix mapping is used and no filter setup -> use suffix >>>>>>>> mapping >>>>>>>> like always >>>>>>>> - If suffix mapping is used and filter setup -> use filter prefix >>>>>>>> mapping >>>>>>>> >>>>>>>>>>[...] If a page is rendered using suffix mapping, >>>>>>>>>>resource paths will use that and not prefix mapping, because faces >>>>>>>>>>mapping is derived from the request path. >>>>>>>>> >>>>>>>>> Nope. That's the whole point of the AdvancedResourceHandler. It >>>>>>>>> always >>>>>>>>> uses prefix mapping, regardless of what the current page is using!! >>>>>>>>> Just check the code (before your commit) ;) >>>>>>>>> >>>>>>>> >>>>>>>> As you can see, I have found many bugs in the previous code. I >>>>>>>> usually >>>>>>>> take my time to check this stuff. In fact, I implemented all >>>>>>>> ResourceHandler implementation in MyFaces, and other alternate >>>>>>>> implementations on tomahawk and sandbox for different use cases, so >>>>>>>> I >>>>>>>> know step by step what says the spec and how the code works. >>>>>>>> >>>>>>>>> I have to say I am not a real fan of this filter. It's like in the >>>>>>>>> old >>>>>>>>> days.. with tomahawk... >>>>>>>>> >>>>>>>> >>>>>>>> Note every JSF library uses a filter! Trinidad, RichFaces, >>>>>>>> PrimeFaces, >>>>>>>> IceFaces. It could be good to find a solution without use a filter >>>>>>>> but >>>>>>>> based on the previous discussion I don't see any. I don't get the >>>>>>>> point. If you have a better idea please send your comments. >>>>>>>> >>>>>>>> I think the strategy proposed is an advance, because you only use it >>>>>>>> when it is necessary. The other alternative is tell users don't use >>>>>>>> suffix mapping. >>>>>>>> >>>>>>>>>> I think the opposite in this case, because the previous syntax is >>>>>>>>>> ambiguous, so you can't decide how to get the libraryName and >>>>>>>>>> resourceName from the resourceBasePath, and the spec requires >>>>>>>>>> describe >>>>>>>>>> that in a explicit way. Think about a resource on: >>>>>>>>>> >>>>>>>>>> /de/mydir/myresource.js (resourceName="de/mydir/myresource.js") >>>>>>>>>> >>>>>>>>>> will produce this request path: >>>>>>>>>> >>>>>>>>>> http://{server}[:port]/{appPath}/javax.faces.resource/de_AT/mydir/myresource.js >>>>>>>>>> >>>>>>>>>> The algorithm will detect de as a locale prefix, mydir as a >>>>>>>>>> library >>>>>>>>>> and myresource.js as a resource name, but that's wrong because the >>>>>>>>>> resource name is de/mydir/myresource.js. >>>>>>>>> >>>>>>>>> I am sorry, but this is wrong, Leo. >>>>>>>>> >>>>>>>>> At first a resourceName of "de/mydir/myresource.js" should not be >>>>>>>>> used. It should rather be resourceName="myresource.js" and >>>>>>>>> libraryName="de/mydir". I know the spec does not explicitly tell us >>>>>>>>> that the resourceName must not be a path, but it is the only way it >>>>>>>>> really makes sence, if you think about it. Otherwise separation of >>>>>>>>> libraryName and resourceName would not be necessary! >>>>>>>>> >>>>>>>> >>>>>>>> The problem is "should not be used" is not an option. I'm saying >>>>>>>> here >>>>>>>> that the same url could be handled by both the default and the >>>>>>>> proposed method. Assume that a developer will do everything you >>>>>>>> imagine is not very realistic. >>>>>>>> >>>>>>>>> Furthermore, a resourceName of "de/mydir/myresource.js" would >>>>>>>>> produce >>>>>>>>> the following path (you did skip "de" and "faces"): >>>>>>>>> >>>>>>>>> http://{server}[:port]/{appPath}/faces/javax.faces.resource/de_AT/de/mydir/myresource.js >>>>>>>>> >>>>>>>>> ..thus producing a resource with libraryName="de/mydir" and >>>>>>>>> resourceName="myresource.js". And this is exactly what is expected >>>>>>>>> of >>>>>>>>> it!! >>>>>>>> >>>>>>>> No, because "de" is a valid locale!. >>>>>>>> >>>>>>>> I think that the relationship between Resource instances and request >>>>>>>> paths generated should be 1:1 and should be symmetric. That means, >>>>>>>> if >>>>>>>> I call this code from a renderer: >>>>>>>> >>>>>>>> ResourceHandler.createResource("","","de/mydir/myresource.js"); >>>>>>>> >>>>>>>> Later the ResourceHandler implementation, when >>>>>>>> handleResourceRequest(FacesContext) is called should call the same >>>>>>>> method, but instead it will call: >>>>>>>> >>>>>>>> ResourceHandler.createResource("de","mydir","myresource.js"); >>>>>>>> >>>>>>>> Who should attend the request? the extended resource handler or the >>>>>>>> default one. The first call expect the default one, but the second?. >>>>>>>> >>>>>>>> In conclusion, if the example does not fulfit the two conditions (be >>>>>>>> 1:1 and symmetric), for any imaginable Resource instance, it will >>>>>>>> not >>>>>>>> be correctly specified. >>>>>>>> >>>>>>>>> >>>>>>>>>> Anyway we need something to "diferentiate" between the old and the >>>>>>>>>> alternate syntax, so use '$/' is as good as any other we can >>>>>>>>>> imagine. >>>>>>>>> >>>>>>>>> I don't think we need to do this differentiation in the first >>>>>>>>> place. I >>>>>>>>> see no reason for it. My code in MyFaces commons (before you >>>>>>>>> committed >>>>>>>>> your stuff) did not use it either and it worked well! Of course, I >>>>>>>>> did >>>>>>>>> not have this filter, but I don't like that anyway (see above). >>>>>>>>> >>>>>>>> >>>>>>>> Why don't you like it? do you have something better in mind?. If you >>>>>>>> want I change of opinion, please provide me with arguments to think >>>>>>>> the opposite. I'm always open to any suggestions or critics. >>>>>>>> >>>>>>>>>> My interest is put this as a module for JSF 2.0, because there is >>>>>>>>>> nothing that prevent us doing it, and this is the "base stone" to >>>>>>>>>> make >>>>>>>>>> components with libraries like dojo, that requires load modules >>>>>>>>>> from >>>>>>>>>> derived base paths. After that, we can push this on the spec for >>>>>>>>>> JSF >>>>>>>>>> 2.2 and the EG will decide. >>>>>>>>> >>>>>>>>> That's the general idea. And note that I am the guy working on the >>>>>>>>> resource handler stuff in the JSF 2.2 EG ;) >>>>>>>>> >>>>>>>>> >>>>>>>>> One more note at the end: actually I am not very happy that you >>>>>>>>> committed your code directly into the svn without providing it as >>>>>>>>> patch before. You did not do any work on the >>>>>>>>> AdvancedResourceHandler >>>>>>>>> before (it was all my code) and it was a pretty big commit (even >>>>>>>>> took >>>>>>>>> 2 commit-mails). Thus you gave me no choice to take a look at it >>>>>>>>> and >>>>>>>>> discuss the changes with you. If I did something like this, the >>>>>>>>> first >>>>>>>>> thing you would do is reverting my commit and providing it as patch >>>>>>>>> so >>>>>>>>> that we can discuss it. I won't do that, but actually it's kinda >>>>>>>>> annoying... >>>>>>>>> >>>>>>>> >>>>>>>> I commited the code instead create a patch, because the code >>>>>>>> commited >>>>>>>> does not override the previous code. So you can put the two >>>>>>>> solutions >>>>>>>> side by side and compare them in a easier way. If something doesn't >>>>>>>> like us, we can remove the added files and that's it, there is no >>>>>>>> harm >>>>>>>> or you don't have to do something difficult to revert the code, >>>>>>>> right?. Note the code has not released yet, so we don't have to >>>>>>>> preserve the package or the class name or any structure. >>>>>>>> >>>>>>>> Things are different when you have already code and you need to >>>>>>>> "override" something, to include something new. A patch is better in >>>>>>>> that case. But in this case, I'm working on a completely different >>>>>>>> solution from scratch. >>>>>>>> >>>>>>>> regards, >>>>>>>> >>>>>>>> Leonardo Uribe >>>>>>>> >>>>>>>>> Regards, >>>>>>>>> Jakob >>>>>>>>> >>>>>>>>> 2011/6/14 Leonardo Uribe <[email protected]>: >>>>>>>>>> Hi Jakob >>>>>>>>>> >>>>>>>>>> 2011/6/13 Jakob Korherr <[email protected]>: >>>>>>>>>>> Hi Leo, >>>>>>>>>>> >>>>>>>>>>> Overall this seems nice, thanks! >>>>>>>>>>> >>>>>>>>>>> However, I have some comments on your solution: >>>>>>>>>>> >>>>>>>>>>> 1) If I have to configure a Filter in web.xml I can just as good >>>>>>>>>>> define a prefix mapping for the FacesServlet. I don't see why an >>>>>>>>>>> additional Filter is better than an additional servlet-mapping. >>>>>>>>>>> So why >>>>>>>>>>> exactly? >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Because set prefix and suffix mapping for the same webapp could >>>>>>>>>> lead >>>>>>>>>> to inconsistencies. If a page is rendered using suffix mapping, >>>>>>>>>> resource paths will use that and not prefix mapping, because faces >>>>>>>>>> mapping is derived from the request path. >>>>>>>>>> >>>>>>>>>> We can't change FacesServlet to only handle resource request for a >>>>>>>>>> specific mapping, but with the filter this is done by default. >>>>>>>>>> Note >>>>>>>>>> the filter will be used only when suffix mapping is used. I tried >>>>>>>>>> it >>>>>>>>>> using FacesServlet but it is useless, because you should do >>>>>>>>>> changes on >>>>>>>>>> jsf impl, so at the end it will only work on myfaces, and the >>>>>>>>>> intention is provide it as a module for any jsf implementation. >>>>>>>>>> >>>>>>>>>>> 2) The locale in the resource path really is essential, please do >>>>>>>>>>> NOT >>>>>>>>>>> remove it. I did a lot of tests with different browsers about >>>>>>>>>>> this and >>>>>>>>>>> you just cannot verify that every user will get the right >>>>>>>>>>> (localized) >>>>>>>>>>> resource, if the user's locale is not on the request path. The >>>>>>>>>>> two >>>>>>>>>>> main problems here are: a) the user changes the locale, but the >>>>>>>>>>> browser uses the cached resource (with the old locale), because >>>>>>>>>>> it >>>>>>>>>>> cannot know that it has changed (some browsers will not even >>>>>>>>>>> start a >>>>>>>>>>> request for it) - however, if the locale is in the path, it will >>>>>>>>>>> change and thus the browser will trigger a new request for the >>>>>>>>>>> resource. b) you cannot really know if there are multiple >>>>>>>>>>> versions of >>>>>>>>>>> a resource for different locales, because you should not scan all >>>>>>>>>>> jar >>>>>>>>>>> files for them (--> remember the performance-issue we had with >>>>>>>>>>> this >>>>>>>>>>> stuff) and furthermore the classpath might change! >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Ok, good to know that. The current code works "forcing" output the >>>>>>>>>> locale, so we can just let things as is. >>>>>>>>>> >>>>>>>>>>> 3) >>>>>>>>>>>> http://{server}[:port]/{appPath}/javax.faces.resource/{locale}/{libraryName}/[resourceName] >>>>>>>>>>>> >>>>>>>>>>>> Unfortunately, this syntax is ambiguous, because it is not >>>>>>>>>>>> possible to >>>>>>>>>>>> identify if the request should be handled by the default >>>>>>>>>>>> algorithm or >>>>>>>>>>>> by the "extended" ResourceHandler. So I tried this one on >>>>>>>>>>>> ExtendedResourceHandler: >>>>>>>>>>>> >>>>>>>>>>>> http://{server}[:port]/{appPath}/javax.faces.resource/$/{locale}/{libraryName}/[resourceName] >>>>>>>>>>> >>>>>>>>>>> This is a nice idea, but I guess this will not be an option for >>>>>>>>>>> the >>>>>>>>>>> JSF 2.2 resource handler (which will most likely be a modified >>>>>>>>>>> version >>>>>>>>>>> of the AdvancedResourceHandler). >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> I think the opposite in this case, because the previous syntax is >>>>>>>>>> ambiguous, so you can't decide how to get the libraryName and >>>>>>>>>> resourceName from the resourceBasePath, and the spec requires >>>>>>>>>> describe >>>>>>>>>> that in a explicit way. Think about a resource on: >>>>>>>>>> >>>>>>>>>> /de/mydir/myresource.js (resourceName="de/mydir/myresource.js") >>>>>>>>>> >>>>>>>>>> will produce this request path: >>>>>>>>>> >>>>>>>>>> http://{server}[:port]/{appPath}/javax.faces.resource/de_AT/mydir/myresource.js >>>>>>>>>> >>>>>>>>>> The algorithm will detect de as a locale prefix, mydir as a >>>>>>>>>> library >>>>>>>>>> and myresource.js as a resource name, but that's wrong because the >>>>>>>>>> resource name is de/mydir/myresource.js. >>>>>>>>>> >>>>>>>>>> Anyway we need something to "diferentiate" between the old and the >>>>>>>>>> alternate syntax, so use '$/' is as good as any other we can >>>>>>>>>> imagine. >>>>>>>>>> My interest is put this as a module for JSF 2.0, because there is >>>>>>>>>> nothing that prevent us doing it, and this is the "base stone" to >>>>>>>>>> make >>>>>>>>>> components with libraries like dojo, that requires load modules >>>>>>>>>> from >>>>>>>>>> derived base paths. After that, we can push this on the spec for >>>>>>>>>> JSF >>>>>>>>>> 2.2 and the EG will decide. >>>>>>>>>> >>>>>>>>>> regards, >>>>>>>>>> >>>>>>>>>> Leonardo Uribe >>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Please take this stuff into account - thanks! >>>>>>>>>>> >>>>>>>>>>> Regards, >>>>>>>>>>> Jakob >>>>>>>>>>> >>>>>>>>>>> 2011/6/14 Leonardo Uribe <[email protected]>: >>>>>>>>>>>> Hi >>>>>>>>>>>> >>>>>>>>>>>> I committed on myfaces-commons-resourcehandler module on trunk >>>>>>>>>>>> an >>>>>>>>>>>> alternative solution for this issue. It is still not complete, >>>>>>>>>>>> so the >>>>>>>>>>>> idea is discuss it. See: >>>>>>>>>>>> >>>>>>>>>>>> https://issues.apache.org/jira/browse/MFCOMMONS-33 >>>>>>>>>>>> >>>>>>>>>>>> From previous discussion, on AdvancedResource handler we have: >>>>>>>>>>>> >>>>>>>>>>>> a. relative paths between resources (css files referencing >>>>>>>>>>>> images >>>>>>>>>>>> without using #resource['..']) >>>>>>>>>>>> b. caching resources in the client (disabled if ProjectStage == >>>>>>>>>>>> Development) >>>>>>>>>>>> c. GZIP compression and local cache in tmp dir (disabled if >>>>>>>>>>>> ProjectStage == Development) >>>>>>>>>>>> d. i18n (supporting country code and language). >>>>>>>>>>>> >>>>>>>>>>>> We had the following proposals: >>>>>>>>>>>> >>>>>>>>>>>> 1. reutilize resource information to prevent unnecessary calls >>>>>>>>>>>> to >>>>>>>>>>>> getResource() (shared ResourceCache). >>>>>>>>>>>> 2. Alternate xml file >>>>>>>>>>>> 3. Make it work with suffix mapping. >>>>>>>>>>>> 4. Add a SPI interface to delegate .xml resource scanning. >>>>>>>>>>>> 5. Use content delivery network (CDN) to load known javascript >>>>>>>>>>>> or other >>>>>>>>>>>> resource files like jQuery or prototype. >>>>>>>>>>>> >>>>>>>>>>>> The objective is provide a solution for all those wanted >>>>>>>>>>>> features. >>>>>>>>>>>> >>>>>>>>>>>> The most important one is number 3. (make it work with suffix >>>>>>>>>>>> mapping), because it limits the scope where a. (relative paths >>>>>>>>>>>> between >>>>>>>>>>>> resources) could be applied. Use a parse on some files it is not >>>>>>>>>>>> a >>>>>>>>>>>> very good solution, so I tried to found an alternative. The most >>>>>>>>>>>> simple one is use a filter that just do the "resource handling" >>>>>>>>>>>> part, >>>>>>>>>>>> just like FacesServlet does. So with suffix mapping you only >>>>>>>>>>>> need to >>>>>>>>>>>> add this on web.xml file: >>>>>>>>>>>> >>>>>>>>>>>> <filter> >>>>>>>>>>>> <filter-name>Faces Filter</filter-name> >>>>>>>>>>>> >>>>>>>>>>>> <filter-class>org.apache.myfaces.commons.resourcehandler.filter.ResourceHandlerFilter</filter-class> >>>>>>>>>>>> </filter> >>>>>>>>>>>> >>>>>>>>>>>> <filter-mapping> >>>>>>>>>>>> <filter-name>Faces Filter</filter-name> >>>>>>>>>>>> <url-pattern>/javax.faces.resource/*</url-pattern> >>>>>>>>>>>> </filter-mapping> >>>>>>>>>>>> >>>>>>>>>>>> and that's it. In this way, there is no need to any parser, just >>>>>>>>>>>> put >>>>>>>>>>>> the files on a library, register it on the xml file. If you are >>>>>>>>>>>> using >>>>>>>>>>>> prefix mapping for Faces Servlet, you will not need that entry, >>>>>>>>>>>> because everything will be handled from Faces Servlet. >>>>>>>>>>>> >>>>>>>>>>>> With this solution, javascript libraries like dojo that loads >>>>>>>>>>>> files or >>>>>>>>>>>> have css resources with url(...) entries will work without any >>>>>>>>>>>> changes. >>>>>>>>>>>> >>>>>>>>>>>> I have seen this issue: >>>>>>>>>>>> >>>>>>>>>>>> https://issues.apache.org/jira/browse/MFCOMMONS-30 >>>>>>>>>>>> Change URL management of Advanced JSF 2 ResourceHandler >>>>>>>>>>>> >>>>>>>>>>>> The idea was use this >>>>>>>>>>>> >>>>>>>>>>>> http://{server}[:port]/{appPath}/javax.faces.resource/{locale}/{libraryName}/[resourceName] >>>>>>>>>>>> >>>>>>>>>>>> Unfortunately, this syntax is ambiguous, because it is not >>>>>>>>>>>> possible to >>>>>>>>>>>> identify if the request should be handled by the default >>>>>>>>>>>> algorithm or >>>>>>>>>>>> by the "extended" ResourceHandler. So I tried this one on >>>>>>>>>>>> ExtendedResourceHandler: >>>>>>>>>>>> >>>>>>>>>>>> http://{server}[:port]/{appPath}/javax.faces.resource/$/{locale}/{libraryName}/[resourceName] >>>>>>>>>>>> >>>>>>>>>>>> The first $ caracter says this extension should be handled by >>>>>>>>>>>> the >>>>>>>>>>>> ExtendedResourceHandler. We can go further and allow this >>>>>>>>>>>> notation: >>>>>>>>>>>> >>>>>>>>>>>> http://{server}[:port]/{appPath}/javax.faces.resource/$$/{libraryName}/[resourceName] >>>>>>>>>>>> >>>>>>>>>>>> In this way there is no ambiguity, and we don't need to force >>>>>>>>>>>> locale >>>>>>>>>>>> to be output. This could be possible too: >>>>>>>>>>>> >>>>>>>>>>>> http://{server}[:port]/{appPath}/javax.faces.resource/$$$/[resourceName] >>>>>>>>>>>> >>>>>>>>>>>> But that it is not really necessary at all. >>>>>>>>>>>> >>>>>>>>>>>> The proposed code still does not contains the options for GZIP >>>>>>>>>>>> compression, because the previous algorithm does not take into >>>>>>>>>>>> account >>>>>>>>>>>> what happen on concurrent requests (two threads modifying the >>>>>>>>>>>> same >>>>>>>>>>>> file at the same time). I did an algorithm for sandbox for JSF >>>>>>>>>>>> 2.0 >>>>>>>>>>>> s:roundedPanel. It uses an application scope map and some >>>>>>>>>>>> synchronized >>>>>>>>>>>> blocks to ensure only one thread writes the file. Exactly the >>>>>>>>>>>> same >>>>>>>>>>>> pattern works in this case, so the only thing we need to do is >>>>>>>>>>>> refactor that code and put it here. >>>>>>>>>>>> >>>>>>>>>>>> Does that sounds good? if no objections commit the proposals >>>>>>>>>>>> here soon. >>>>>>>>>>>> >>>>>>>>>>>> regards, >>>>>>>>>>>> >>>>>>>>>>>> Leonardo Uribe >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> -- >>>>>>>>>>> Jakob Korherr >>>>>>>>>>> >>>>>>>>>>> blog: http://www.jakobk.com >>>>>>>>>>> twitter: http://twitter.com/jakobkorherr >>>>>>>>>>> work: http://www.irian.at >>>>>>>>>>> >>>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> -- >>>>>>>>> Jakob Korherr >>>>>>>>> >>>>>>>>> blog: http://www.jakobk.com >>>>>>>>> twitter: http://twitter.com/jakobkorherr >>>>>>>>> work: http://www.irian.at >>>>>>>>> >>>>>>>> >>>>>>> >>>>>> >>>>>> >>>>>> >>>>>> -- >>>>>> >>>>>> http://www.irian.at >>>>>> >>>>>> Your JSF powerhouse - >>>>>> JSF Consulting, Development and >>>>>> Courses in English and German >>>>>> >>>>>> Professional Support for Apache MyFaces >>>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> Jakob Korherr >>>>> >>>>> blog: http://www.jakobk.com >>>>> twitter: http://twitter.com/jakobkorherr >>>>> work: http://www.irian.at >>>>> >>>> >>> >>> >>> >>> -- >>> Jakob Korherr >>> >>> blog: http://www.jakobk.com >>> twitter: http://twitter.com/jakobkorherr >>> work: http://www.irian.at >>> >> > > > > -- > Jakob Korherr > > blog: http://www.jakobk.com > twitter: http://twitter.com/jakobkorherr > work: http://www.irian.at > -- http://www.irian.at Your JSF powerhouse - JSF Consulting, Development and Courses in English and German Professional Support for Apache MyFaces
