Skip to content
This repository has been archived by the owner on Sep 5, 2023. It is now read-only.

Relative Resources #947

Closed
glassfishrobot opened this issue Mar 9, 2011 · 26 comments
Closed

Relative Resources #947

glassfishrobot opened this issue Mar 9, 2011 · 26 comments

Comments

@glassfishrobot
Copy link

https://issues.apache.org/jira/browse/MFCOMMONS-29

The features of this ResourceHandler include the following:

  • relative paths between resources (css files referencing images
    without using #resource['..'])
  • caching resources in the client (disabled if ProjectStage == Development)
  • GZIP compression and local cache in tmp dir (disabled if
    ProjectStage == Development)
  • i18n (supporting country code and language).

In addition, it does NOT support ValueExpressions in resource files
for performance reasons.

The most important feature, in my opinion, is how the resource URL is
built, e.g. /faces/javax.faces.resource/de_AT/$/some/library/$/my/resource.css

... because it permits resources referencing other resources without

{resource['...']}

(e.g. css files referencing images or other css
files). With the standard ResourceHandler this is 1) annoying if you
have to change the files you get from your designer and 2) a
performance bottleneck, because resources with ValueExpressions are
not cached and also regenerated for each request.

Furthermore, the resource URL contains the locale and thus you have no
problems with cached resources if a users changes the locale, because
he/she will get a new URL and thus a new resource (the right one).

Affected Versions

[2.2]

@glassfishrobot
Copy link
Author

Reported by @edburns

@glassfishrobot
Copy link
Author

@glassfishrobot
Copy link
Author

@glassfishrobot
Copy link
Author

jakobkorherr said:
add duplicate links.

@glassfishrobot
Copy link
Author

jakobkorherr said:
Just found out that ICEFaces actually provides a tool for processing url() references in css files which are served by JSF 2.0. For example, this tool creates url(#

{resource['org.site.lib/images/background.png']}

) out of url(../images/background.png).

This shows the big impact of this issue, I think.

See http://wiki.icefaces.org/display/ICE/ACE+CSS+URL+Mapping for more details!

We seriously need to fix this with JSF 2.2! Such (annoying) preprocessing should not be necessary.

@glassfishrobot
Copy link
Author

dueni said:
Hi Jakob,

it would be usefull if there was a way to specify resources depending on the active ProjectStage - e.g. for css and Javascript files, to allow using packaged resources normally but uncompressed css/javascript when ProjectStage is set to Development.

I was discussing this once with someone and we ended up in a possible solution for that to put additional includeProjectStage/excludeProjectStage condition attributes on @ResourceDependency annotation and probably also same attributes on outputStylesheet/outputScript tags.

Might be this ends up in an additional independent issue, but as you are going to work on ResourceHandling anyway I feel adding it here is ok.

regards
Hanspeter

@glassfishrobot
Copy link
Author

lu4242 said:
In MyFaces and Tomahawk a custom hack is used to check if the project stage is Development and if a resource under META-INF/internal-resources (or in tomahawk META-INF/uncompressed-js-resources), just take this instead the compressed version used in Production stage.

I believe that it could be more simple to assume a "mirror uncompressed" location, and in practice use some plugin to compress the resources, and add the logic on the default (or custom) ResourceHandler algorithm.

EB> This approach breaks down when there is not a 1:1 mapping between
EB> compressed and non-comporessed resources. For example, when you
EB> want all your JS in one compressed file at Production time, and want
EB> several smaller, non-compressed files, at Development time.

@glassfishrobot
Copy link
Author

jakobkorherr said:
Hi Hanspeter,

This is a very, very nice idea! I will prototype that in my relative-resource-handler at apache-extras (see http://code.google.com/a/apache-extras.org/p/relative-resource-handler/).

Also: Since I will have more time in the next two weeks, I really do hope to get some work done for the spec!

Regards,
Jakob

@glassfishrobot
Copy link
Author

dueni said:
Hi Jakob,

any progress here?

I wanted to add something about the ProjectStage dependent resources. There might be two options for it:

1. use a project stage dependent resource path in the jar (similar to Locale handling with fallback). This is useful if the resource is the same name but only compressed for production, e.g.

myJs/some.js
myJs/production/some.js             (compressed some.js)

2. because the JS files may get pretty big, we would like to use multiple JS files for development but combine/compress a number of such JS files to one for production. This means the number of resource dependencies change depending on project stage.

myJs/funct-a.js
myJs/funct-b.js
myJs/funct-c.js
myJs/{production/}funct-all.js      (compressed combination of funct-*.js files)

So for example, it should be possible to state one component needs funct-a.js and funct-b.js when in project stage Development and only funct-all.js when in project stage Production.

I think possibility 1 is a little closer to what Leonardo mentioned about the MyFaces specific hack.
I really would like to have a specified way to handle project-stage specific resources, this might need some discussion in expert group though.

Cheers
Hanspeter

@glassfishrobot
Copy link
Author

jakobkorherr said:
Hi Hanspeter,

Currently I am trying to convince a professor at Vienna university of technology to let me write about the relative resource handler for my bachelor thesis. If this will be accepted, I will have a lot more time for the resource handler.

The idea is really very, very great and I'd like to do some prototyping here. However, I don't know if we should really follow a convention-over-configuration approach. I am actually not sure if we can find a convention for the resource name that will fit in most scenarios. Maybe we need some configuration mechanism here...

Regards,
Jakob

@glassfishrobot
Copy link
Author

dueni said:
Hi all.

For multiple skins or theme support it will be necessary that the resource path may contain an optional skin or theme-path part.

Skin-one
 /resources/skin-one/css/main.css

 Skin-two
 /resources/skin-two/css/main.css

The reference to this resource could be:

<h:outputStylesheet name="main.css" library="css" />

I have kind of such an implementation, but it is probably to much integrated with our Skin interface. It should be a more general solution.

Regards
Hanspeter

@glassfishrobot
Copy link
Author

jakobkorherr said:
Hi hanspeter,

You are totally right! In my resource handler I called it "support for multi-tenancy", however, this is not implemented yet.

Actually you need to add every information you need to determine the correct resource into the resource path, thus it somehow is a REST url. I also added a resource-version to the path in order to deal with resource-update-browser-cache problems.

Regards,
Jakob

@glassfishrobot
Copy link
Author

@edburns said:
Jakob, can you please hack upon this sample war to make it show the problem? The current war does use relative resources, but the browser is able to resolve them. Can you make it so the browser cannot resolve them?

@glassfishrobot
Copy link
Author

File: sample.zip
Attached By: @edburns

@glassfishrobot
Copy link
Author

jakobkorherr said:
Hi Ed,

Your sample is somehow funny. You use a css file in webapp/resources/library/style.css using relative paths like this: url(../../included.css) and url(../../expert-draft-bg.png). The two referenced resources, of course, are located two folders up in the directory tree (directly in webapp).

Now as it would seem to be logical that this works, it really is a coincidence. You see, style.css is loaded via the following url:

http://localhost:8080/faces/javax.faces.resource/style.css?ln=library

Thus, included.css and expert-draft-bg.png are loaded by the browser using the following urls:

http://localhost:8080/included.css http://localhost:8080/expert-draft-bg.png

The 1st ".." removed "javax.faces.resource" and the 2nd ".." removed "faces" (however, you would actually think that the 1st ".." removes library and the 2nd ".." removes "resources"). This, of course, only works because tomcat (or any other servlet container) serves the two files directly, and it has nothing to do with the JSF resource handler (e.g. ValueExpressions won't work!).

Now, there are a number of possibilities to break the example:

  1. use .jsf instead of /faces/ FacesServlet mapping
  2. locate the two resources in the same folder as style.css (while removing the ".." sequences in style.css)
  3. locate the two resources in the classpath (META-INF/resources)
    ...

I used the 2nd of the above options in my sample_broken.zip.

Here, style.css still gets loaded via:

http://localhost:8080/faces/javax.faces.resource/style.css?ln=library

But now the browser tries to locate included.css and expert-draft-bg.png using these urls:

http://localhost:8080/faces/javax.faces.resource/included.css http://localhost:8080/faces/javax.faces.resource/expert-draft-bg.png

Which does NOT work, because the library request parameter is missing. My approach (http://code.google.com/a/apache-extras.org/p/relative-resource-handler/) creates an url in which the library is included in the url path, thus this will work.

If you have any further questions, please ask!

Regards,
Jakob

@glassfishrobot
Copy link
Author

jakobkorherr said:
Added sample_broken.zip

@glassfishrobot
Copy link
Author

File: sample_broken.zip
Attached By: jakobkorherr

@glassfishrobot
Copy link
Author

@edburns said:
Thanks for demonstrating to me exactly how this is broken.

Now I can proceed to better see how to fix it!

@glassfishrobot
Copy link
Author

@edburns said:
Looking at your relative-resource handler, it is immediately apparent that the ability for the relative resources to even work is based on how you are encoding the library name differently from what is specified. As stated in the javadocs for RelativeResourceHandler, you have to use

META-INF/relative-resources.xml

to declare libraries and we can't accept that requirement in the spec. Also, the stated limitation of only being able to work with prefix mapped JSF runtimes is unacceptable.

I can see why you made these decisions and how they enable the nice features of your Relative ResourceHandler, but we need to figure out how to do what you request without making unacceptable compromises.

@glassfishrobot
Copy link
Author

@edburns said:
Jakob, what is the main reason for being dissatisfied with this syntax for relative resources?

css_master.css:

@import url(#

{resource['this:layout.css']}

);

Is it performance?

@glassfishrobot
Copy link
Author

jakobkorherr said:
The need to have the libraryName configured in relative-resources.xml does only exist, because I needed a way to enable the RelativeResourceHandler only for certain libraries. This would not be necessary if the standard ResourceHandler already uses the "relative-mechanism" (for all libraries).

There are many reasons:

  1. Acceptance: There is no other framework (at least which I know of), in which you cannot use relative paths between resources as they would work in the file system. Nearly every IDE supports "resource-exists-checks" in css files with relative paths in the file system, and these IDEs will mark #

{resource[]}

url references as errors. Every server (http or servlet container), CDN,... supports relative paths in the URLs like a normal file system, why should JSF do this differently?

  1. Effort: You need quite a lot of time to change a big CSS framework (which you will get from your designers) into a working JSF version. And remember, next day the designer may change something, then you will get a new version of the whole CSS framework, and the work starts again...

  2. Performance: Actually, having ValueExpressions in resource files is not only a performance killer, it also gives the developer the impression as if she could change resource file contents in every request, whereas she really cannot, because the resource will get cached by the browser/proxy.

I actually would not use the current JSF ResourceHandler because of these points and instead let tomcat (or even weblets) handle my resources, because they both support relative paths like a calm.

@glassfishrobot
Copy link
Author

@edburns said:
A resource path from Jakob's impl looks like
"/javax.faces.resource/1.0.0/en_US/css/style.css". Does that 1.0.0
refer to library version or resource version?

Here's a clue, from RelativeResourceHandler#132.

// skip version in url (first part, only there to avoid cache problems on updates)
final int versionSlash = resourceName.indexOf('/');

But that still doesn't answer my question. What does the 1.0.0 mean?

Jakob's ResourceHandler.createResource() allows the entire resourceId to
be in the "resourceName", which it re-interprets according to its own
rules if it determines that the library is not a JSF 2.0 style resource
library.

JK> The need to have the libraryName configured in
JK> relative-resources.xml does only exist, because I needed a way to
JK> enable the RelativeResourceHandler only for certain libraries. This
JK> would not be necessary if the standard ResourceHandler already uses
JK> the "relative-mechanism" (for all libraries).

Ok, let's say we make relative libraries the default for prefix mapped
applications. If we have a jar in the classpath that contains a library
that is arranged according to the JSF 2.0 spec for resource libraries,
we now we need some way to detect that case and use the JSF 2.0 style
arrangement, right?

@glassfishrobot
Copy link
Author

@edburns said:
Set priority to baseline ahead of JSF 2.3 triage. Priorities will be assigned accurately after this exercise.

@glassfishrobot
Copy link
Author

@manfredriem said:
Setting priority to Critical

@glassfishrobot
Copy link
Author

This issue was imported from java.net JIRA JAVASERVERFACES_SPEC_PUBLIC-947

@glassfishrobot
Copy link
Author

Closing this as this issue is migrated to jakartaee/faces#947

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants