2010/10/13 Andy Schwartz <andy.schwartz@oracle.com>
Right now, ViewHandler.deriveViewId() is used by NavigationHandler and in that use case it is necessary the viewId is being checked for existence, or in other words, if the physical resource tied to the viewId exists or not (for preemptive navigation). Here we have two options:
- Add a method like ViewHandler.getViewDeclarationLanguageFromRawViewId
- Add another method that do the same as deriveViewId() but do not check for viewId existence, to allow call it from Restore View Phase and do not break existing TCK tests.
This split approach is particularly awkward since ExternalContext.getResource() is used more generically than ResourceResolver - ie. ExternalContext.getResource() may be called for arbitrary resource retrieval, whereas we are particularly interested in view resolving.
In theory just override or wrap ResourceResolver should be enough,
and we should prevent override ExternalContext.getResource().
If we had access to an application-level (VDL-independent) ResourceResolver, the JSF implementations could use this to check for the existence of views when deriving view ids (and elsewhere) without having to go through the ViewDeclarationLanguageFactory.
I agree with this one too. In theory, the VDL is responsible to build views, so it should use some strategy to retrieve them (it is the "client"). Use a strategy per VDL seems theorically reasonable but in practice, since each VDL only handle files mutually exclusive with other VDL's, use a shared ResourceResolver per all VDL is ok in my opinion.
I don't think it would be especially hard to make the ResourceResolver more general-purpose. We would likely want to add a new version of this class outside of the Facelets packaging and possibly re-parent the existing Facelets ResourceResolver to the new API. Or, at least, we would want to provide the ability to transparently adopt the old Facelets ResourceResolver to the new generic ResourceResolver.
In my opinion, it should be an application scope object and developers should be able to add wrappers through faces-config.xml inside <application> tag. It would be great!.
Anyway, there is still open the question about if the spec should allow create wrapper per VDL from faces-config.xml. There are some use cases when this could be helpful, like allow extend facelets an add custom "attached objects".
Another small change that might be helpful... in order to answer the question of whether or not a resource exists, we currently need to literally cough up an URL. In our case, we might be able to optimize if we just had to test for existence as opposed to return a reference to the resource. Perhaps we could consider adding exists() method to the generic ResourceResolver. By default this would just do "resolveUrl() != null", but this could be optimized in other implementations.
Yes it could be, but anyway we need the method existsViewId on ViewDeclarationLanguage (and that one will call the hypothetical method ResourceResolver.exists() ). Why? because the VDL should be responsible to indicate if the viewId is valid before check for existence. In the patch proposed this check is done before call ResourceResolver stuff.
if (vdlFactory.existsViewId(context, viewId)) { ... }
ViewDeclarationLanguage vdl = getViewDeclarationLanguage(viewId)
if (vdl.viewExists(context, viewId)) { ... }
Thoughts?
+1 on fix all that stuff before get 2.1 out.
best regards,
Leonardo Uribe