Hi 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?
Ok, now I get it. So if we have a suffix-mapping request we can derive the prefix-mapping alternative. I only see one use case where this could fail (special OSGI setup) but in that case you can always define prefix mapping from start. I remember that MyFaces 1.1.x used to parse web.xml to get that information. It that way we can just get rid of the filter and say "... always provide a prefix mapping for FacesServlet ..." Anyway, we need to implement that and change some dependecies in that project to make it work. best regards, Leonardo Uribe > > 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 >
