jsr372-experts@javaserverfaces-spec-public.java.net

[jsr372-experts] Re: Url mapping

From: arjan tijms <arjan.tijms_at_gmail.com>
Date: Tue, 2 Dec 2014 21:10:28 +0100

Hi,

On Tuesday, December 2, 2014, Josh Juneau <juneau001_at_gmail.com> wrote:

> Sorry or the late response to this thread. I like all of the ideas put
> forth, and I think that Leonardo's last message pertaining to a
> META-INF/views folder would be a clean solution for developing
> extensionless URLs.
>

As a historical reference, I originally proposed the views folder over two
years ago, and when thinking about that, the extensionless idea kinda
naturally grew out of that (see
https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1099). It's nice
to see that the reverse is true as well, when thinking about extensionless
URLs, the views folder naturally comes up as well ;)


> While it is not always the best solution, sometimes files need to be
> altered while in production. Perhaps a URL changes, or maybe even a simple
> string of text. If the META-INF/views were to be scanned once at
> application start-up, then any changes to the files would require an
> application restart or a complete re-deploy.
>

After I implemented this feature in OmniFaces we encountered the issue
where views were added or removed during development. The solution that we
used here is that depending on a setting, the views folder is scanned again
when a view is not found.

Changing text doesn't matter. The facility doesn't scan and hold in memory
the content of views, but merely the names. In other words, it indexes
which views there are available, but the content is still resolved in the
way as it is always resolved.

Kind regards,
Arjan Tijms




> This is not necessarily a bad thing, as it would force users to adhere to
> proper standards...but it could be an annoyance if only minor adjustments
> needed to be made to the views. Just thought I'd add my two cents.
>
> Best Regards
>




>
> Josh Juneau
> juneau001_at_gmail.com
> http://jj-blogger.blogspot.com
> https://www.apress.com/index.php/author/author/view/id/1866
>
>
> On Thu, Nov 13, 2014 at 2:08 PM, Leonardo Uribe <leonardo.uribe_at_irian.at>
> wrote:
>
>> Hi
>>
>> EB> Leonardo, I share your skepticism of the merits of this proposal.
>> EB> Especially when we consider that we could propose something to the
>> EB> servlet EG, the broad changes included in this proposal require much
>> EB> more refinement and discussion, and prototyping.
>>
>> I just want to put all the elements on the table, to get a clear idea
>> about the trade-offs.
>>
>> EB> My first impression is that this idea would be better served in the
>> MVC
>> EB> spec.
>>
>> I think JSF has some special requeriments that we need to consider:
>>
>> - It is necessary to generate urls based on the mapping information.
>> - It is necessary to interpret the url later and transform it to
>> produce a "normalized" form that can be processed by JSF.
>> - The mapping must be calculated on application startup.
>>
>> I think it fits better in JSF, because we need to control some steps
>> inside JSF.
>>
>> AT> The arguments are not that different from what CDI extensions do. The
>> AT> CDI runtime scans through an amazing amount of classes and calls an
>> AT> arbitrary amount of extensions, potentially for each and every class
>> AT> encountered. Extensions may do expensive and time consuming things
>> AT> like scanning for custom annotations and accessing things via
>> AT> reflection.
>>
>> As far as I know, CDI does not load the classes, it just scan them with a
>> flat scanner, that does not load any class. Here we are talking about
>> "parse" xml files, create a UIViewRoot and the metadata tree (without
>> a UIViewRoot, there is no metadata), and finally grab the metadata. That
>> parsing forces to load every class related to every component used in
>> the application.
>>
>>
>>
>> I would like to do a counter-proposal.
>>
>> Suppose there is a special web folder called META-INF/views. It has
>> the following conditions:
>>
>> - Every file there will be mapped to an extensionless url without
>> exception, no questions asked.
>> - If a file name or a folder name contains '{...}', it means that
>> this part of the url is a path param that is transformed later to a
>> query param. Note '{' and '}' are considered "unwise" characters
>> on a url, so nobody uses it, but are valid characters for file names
>> in windows and linux systems.
>> - JSF specify that at startup it will scan all files inside that
>> folder and based on that (just read the file name) it will build a
>> mapping tree and update the servlet mappings.
>> - Any directory inside META-INF/views has the same logic used in
>> Faces Flows, so you can define flows here too.
>> - URL mapping can be done inside faces-config.xml too.
>>
>> Example:
>>
>> webapp
>> |-- WEB-INF
>> | |-- web.xml
>> | +-- faces-config.xml
>> |-- META-INF
>> |-- views
>> |-- books
>> |-- {bookId}.xhtml
>> |-- {bookId}
>> +-- showAuthors.xhtml
>>
>>
>> This is how JSF map the information:
>>
>> /books/{bookId}.xhtml maps to
>> http://localhost:8080/myapp/books/1
>>
>> /books/{bookId}/showAuthors.xhtml maps to
>> http://localhost:8080/myapp/books/1/showAuthors
>>
>> Let's review the five point list you suggest:
>>
>> 1. Default mapping of FacesServlet to .xhtml
>>
>> We need a method on ViewDeclarationLanguage, for example
>> VDL.handleViewId(FacesContext facesContext, String viewId)
>> that just check if the viewId (/books/{bookId}.xhtml) can be
>> handled by the VDL, without check if the resource exists
>> (VDL.viewExists()). The algorithm could iterate over all
>> VDL available.
>>
>> 2. Plain extensionless mapping
>> 3. Extensionless mapping + availability of path info
>>
>> JSF should not see the incoming URL. Instead it just see the
>> viewId and some extra parameters created by the url mapping
>> algorithm, that can be handled as view params.
>>
>> http://localhost:8080/myapp/books/1
>>
>> will be seen in JSF as:
>>
>> viewId: /books/{bookId}.xhtml
>> requestParam: bookId = 1
>>
>> inside {bookId}.xhtml
>>
>> <f:metadata>
>> <f:viewParam name="bookId" value="..."/>
>> </f:metadata>
>>
>> To generate a link you should write inside the page:
>>
>> <h:link outcome="books">
>> <f:param name="bookId" value="1">
>> </h:link>
>>
>> <h:link outcome="books/showAuthors">
>> <f:param name="bookId" value="1">
>> </h:link>
>>
>> Note you need to know the params defined to calculate the right
>> outcome, so we need some changes over navigation algorithm.
>>
>> It can be done in different ways. A decorator over ExternalContext,
>> an ViewURLMapper/ViewURLMapperFactory class that decouple the
>> mapping logic we have in JSF 2.2 section 2.2.1.
>>
>> 4. Rules based URL mapping with simple pattern based rules
>> 5. Rules based URL mapping with rewrite rules of arbitrary complexity
>>
>> I would like to ask you guys a question: How much flexibility is required?
>> Could it be that a simple path param mapping is all that we need?.
>>
>> We can provide further flexibility using some kind of pattern
>> matching, but I doubt about its usefulness. Most of the time what the
>> developers want is introduce a param in the url and use the same view
>> for multiple urls.
>>
>>
>> In my personal opinion, the proposal has the following advantages:
>>
>> - Provide an abstraction that hides how the urls are generated.
>> - Hide how the urls are generated allow use the same logic in different
>> situations with no changes. For example, portlets can just provide
>> its custom url mapping approach on top of the existing one. The
>> application will work in any case
>> - Reuse existing logic in JSF.
>> - You can take a look at the file tree and in one shot you can
>> see the url mapping structure of your application. No need to open extra
>> files.
>> - You don't need to compile .xhtml files, create component trees.
>> It will be a small hit on application startup, a new SPI interface to
>> give the server the option to list the files and that's it.
>> - It would be possible to bundle an entire application inside a jar,
>> because we will have a way to add views to an application.
>> - It could be possible to secure the valid view urls of an application.
>> Using some config inside faces-config.xml, define a check to do before
>> or after the view is loaded to check if it is valid to show the view
>> or not and if not deal with it. This logic is usually scattered inside
>> ViewHandler.
>>
>> Suggestions are welcome.
>>
>> regards,
>>
>> Leonardo Uribe
>>
>>
>> 2014-11-11 12:02 GMT-05:00 arjan tijms <arjan.tijms_at_gmail.com>:
>> > Hi,
>> >
>> > On Mon, Nov 10, 2014 at 11:51 PM, Edward Burns <edward.burns_at_oracle.com>
>> wrote:
>> >> Especially when we consider that we could propose something to the
>> >> servlet EG, the broad changes included in this proposal require much
>> >> more refinement and discussion, and prototyping.
>> >
>> > I think it does depend a little on how far we're willing to take this.
>> > There seem to be several ideas floating around, all somehow related to
>> > the topic of "mapping". With an increasing level of complexity these
>> > seem to be:
>> >
>> > 1. Default mapping of FacesServlet to .xhtml
>> > 2. Plain extensionless mapping
>> > 3. Extensionless mapping + availability of path info
>> > 4. Rules based URL mapping with simple pattern based rules
>> > 5. Rules based URL mapping with rewrite rules of arbitrary complexity
>> >
>> > Option 1. is completely trivial to implement, but really only makes
>> > sense when it's a default mapping.
>> >
>> > Option 2. is more involved, but as far as rule processing goes also
>> > trivial, since there's no user provided rule to speak off. It's
>> > completely convention and defaults based. If someone wants a
>> > /book/edit there needs to be a folder "book" with a view "edit.xhtml".
>> >
>> > Option 3. is like option 2, but just like Servlets had from day one,
>> > adds the ability to expose the extra paths after the resource mapping.
>> > E.g.:
>> >
>> > /foo/bar is requested
>> > /foo/bar.xhtml doesn't exist, but /foo.xhtml does
>> > Instead of sending a 404, use /foo.xhtml, preferably with "/bar" as
>> > request.getPathInfo()
>> >
>> > This rather useful feature is known in the Apache HTTPD+PHP world
>> > known as "MultiViews".
>> >
>> > Option 4. and especially 5. are slowly getting more complicated. What
>> > syntax do we allow? Only simple name mapping ("foo" maps to "bar") and
>> > simple path to parameter mapping? E.g. /12 becomes userid=12 Or do we
>> > have PrettyFaces/Rewrite-like rules, which if I'm not mistaken are of
>> > nearly arbitrary complexity?
>> >
>> > Kind regards,
>> > Arjan Tijms
>>
>
>