I have a modular JSF application. Facelets are stored in the module in META-INF/resources. I added a custom FaceletsResourceResolver (as demonstrated in this post How to create a modular JSF 2.0 application?) and all of this works well with .xhtml - Files. Now I am trying to add other resources in the same fashion and it's not working.
Let's say I have this structure in the module:
/META-INF/resources
/META-INF/resources/foo
/META-INF/resources/foo/bar.xhtml
/META-INF/resources/foo/bar.js
Now the application resolves /foo/bar.xhtml just fine. But attempts to fetch /foo/bar.js simply fail with 404. I tried using
<h:outputScript library="modulename" name="foo/bar.js" />
as well as direct reference
<script language="text/javascript" src="/context/foo/bar.js"/>
both to no avail. I feel I am missing something. Can someone help me?
PS: using Apache Tomcat 6 and Eclipse-Juno for development.
I'll ignore the fact that the mentioned versions in your question in its current form is confusing. JSF 2.2 (as you tagged) requires a minimum of Servlet 3.0. Tomcat 6 (as you mentioned) is a Servlet 2.5 container (and a quite old one either). This is not going to work together. Also noted should be that the FaceletsResourceResolver which you found there is only necessary when you're using Servlet 2.5 or are using a very early JBoss AS 6 version.
The library name does here not represent the JAR file name, but the subfolder where all of those resources commonly belong to. So when you have a
<h:outputScript library="modulename" name="foo/bar.js" />
then the following structure is expected in the JAR:
/META-INF/resources/modulename
/META-INF/resources/modulename/foo
/META-INF/resources/modulename/foo/bar.xhtml
/META-INF/resources/modulename/foo/bar.js
Alternatively, you can keep your original structure and use
<h:outputScript library="foo" name="bar.js" />
depending on the meaning of the actual value of foo.
See also:
Packaging Facelets files (templates, includes, composites) in a JAR
Related
I have some Facelets files like below.
WebContent
|-- index.xhtml
|-- register.xhtml
|-- templates
| |--userForm.xhtml
| `--banner.xhtml
:
Both pages are using templates from /templates directory. My /index.xhtml opens fine in browser. I get the generated HTML output. I have a link in /index.xhtml file to /register.xhtml file.
However, my /register.xhtml is not getting parsed and returns as plain XHTML / raw XML instead of its generated HTML output. All EL expressions in form of #{...} are displayed as-is instead of that their results are being printed. When I rightclick page in browser and do View page source, then I still see the original XHTML source code instead of the generated HTML output. For example, the <h:body> did not become a <body>. It looks like that the template is not being executed.
However, when I open the /register.xhtml like /faces/register.xhtml in browser's address bar, then it displays correctly. How is this caused and how can I solve it?
There are three main causes.
FacesServlet is not invoked.
XML namespace URIs are missing or wrong.
Multiple JSF implemenations have been loaded.
1. Make sure that URL matches FacesServlet mapping
The URL of the link (the URL as you see in browser's address bar) has to match the <url-pattern> of the FacesServlet as definied in web.xml in order to get all the JSF works to run. The FacesServlet is the one responsible for parsing the XHTML file, collecting submitted form values, performing conversion/validation, updating models, invoking actions and generating HTML output. If you don't invoke the FacesServlet by URL, then all you would get (and see via rightclick, View Source in browser) is indeed the raw XHTML source code.
If the <url-pattern> is for example *.jsf, then the link should point to /register.jsf and not /register.xhtml. If it's for example /faces/*, like you have, then the link should point to /faces/register.xhtml and not /register.xhtml. One way to avoid this confusion is to just change the <url-pattern> from /faces/* to *.xhtml. The below is thus the ideal mapping:
<servlet>
<servlet-name>facesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
If you can't change the <url-pattern> to *.xhtml for some reason, then you probably would also like to prevent endusers from directly accessing XHTML source code files by URL. In that case you can add a <security-constraint> on the <url-pattern> of *.xhtml with an empty <auth-constraint> in web.xml which prevents that:
<security-constraint>
<display-name>Restrict direct access to XHTML files</display-name>
<web-resource-collection>
<web-resource-name>XHTML files</web-resource-name>
<url-pattern>*.xhtml</url-pattern>
</web-resource-collection>
<auth-constraint />
</security-constraint>
JSF 2.3 which was introduced April 2017 has already solved all of above by automatically registering the FacesServlet on an URL pattern of *.xhtml during webapp's startup. The alternative is thus to simply upgrade to latest available JSF version which should be JSF 2.3 or higher. But ideally you should still explicitly register the FacesServlet on only one URL pattern of *.xhtml because having multiple possible URLs for exactly the same resource like /register.xhtml, /register.jsf, /register.faces and /faces/register.xhtml is bad for SEO.
See also:
Set default home page via <welcome-file> in JSF project
Opening JSF Facelets page shows "This XML file does not appear to have any style information associated with it."
Sometimes I see JSF URL is *.jsf, sometimes *.xhtml and sometimes /faces/*. Why?
JavaServer Faces 2.2 and HTML5 support, why is XHTML still being used
Which XHTML files do I need to put in /WEB-INF and which not?
Our servlets wiki - to learn the mandatory basics about servlets
2. Make sure that XML namespaces match JSF version
Since introduction of JSF 2.2, another probable cause is that XML namespaces don't match the JSF version. The xmlns.jcp.org like below is new since JSF 2.2 and does not work in older JSF versions. The symptoms are almost the same as if the FacesServlet is not invoked.
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
If you can't upgrade to JSF 2.2 or higher, then you need to use the old java.sun.com XML namespaces instead:
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
But ideally you should always use the latest version where available.
See also:
Which XML namespace to use with JSF 2.2 and up
JSF tags not executed
Warning: This page calls for XML namespace http://xmlns.jcp.org/jsf/XXX declared with prefix XXX but no taglibrary exists for that namespace
3. Multiple JSF implementations have been loaded
One more probable cause is that multiple JSF implementations have been loaded by your webapp, conflicting and corrupting each other. For example, when your webapp's runtime classpath is polluted with multiple different versioned JSF libraries, or in the specific Mojarra 2.x + Tomcat 8.x combination, when there's an unnecessary ConfigureListener entry in webapp's web.xml causing it to be loaded twice.
<!-- You MUST remove this one from web.xml! -->
<!-- This is actually a workaround for buggy GlassFish3 and Jetty servers. -->
<!-- When leaving this in and you're targeting Tomcat, you'll run into trouble. -->
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
When using Maven, make absolutely sure that you declare the dependencies the right way and that you understand dependency scopes. Importantingly, do not bundle dependencies in webapp when those are already provided by the target server.
See also:
Configuration of com.sun.faces.config.ConfigureListener
How to properly install and configure JSF libraries via Maven?
Make sure that you learn JSF the right way
JSF has a very steep learning curve for those unfamiliar with basic HTTP, HTML and Servlets. There are a lot of low quality resources on the Internet. Please ignore code snippet scraping sites maintained by amateurs with primary focus on advertisement income instead of on teaching, such as roseindia, tutorialspoint, javabeat, baeldung, etc. They are easily recognizable by disturbing advertising links/banners. Also please ignore resources dealing with jurassic JSF 1.x. They are easily recognizable by using JSP files instead of XHTML files. JSP as view technology was deprecated since JSF 2.0 at 2009 already.
To get started the right way, start at our JSF wiki page and order an authoritative book.
See also:
Java / Jakarta EE web development, where do I start and what skills do I need?
What is the need of JSF, when UI can be achieved with JavaScript libraries such as jQuery and AngularJS
I am starting to explore JSF 2 facelet and I would like to test this in a simple project.
I just have some query regarding the file structure in JSF 2. When I was using Spring,
I use to put all my pages under WEB-INF so that they wont be accessible to the browser.
I notice in JSF 2, you should put your *.xhtml outside of WEB-INF and allow access to them thru
the Faces Servlet.
Question, does this mean that all enterprise application that utilizes JSF always put
a security constraint in their web.xml?
<security-constraint>
<web-resource-collection>
<web-resource-name>XHTML files</web-resource-name>
<url-pattern>*.xhtml</url-pattern>
</web-resource-collection>
<auth-constraint />
</security-constraint>
Or they are using some sort of a filter, that traps all incoming request and then reject request
that has *.xhtml?
Is my understanding correct and if so which one is more apt to be used?
Thanks
A third alternative in JSF 2.x is to map the FacesServlet just straight on *.xhtml instead of *.jsf or whatever. This way you don't need to cobble with security constraints or filters to prevent endusers from directly accessing *.xhtml files. It has the only disadvantage that you cannot serve "plain vanilla" XHTML files without invoking the FacesServlet, but that would in turn already not make much sense, because such files should technically have the *.html extension.
Please note that this doesn't work in old JSF 1.x. The FacesServlet would run in an infinite loop invoking itself again and again.
I started to use JSF 2.0 recently and I don't understand completely how I need to configure the javax.faces.webapp.FacesServlet to correctly handle resources.
For example, If I decided to create a web application with .xhtml files and .jsp files and I want both them to use jsf technology how am I supposed to configure the jsf servlet to handle both?
Sometimes I found example where the servlet url pattern is just /faces/*
thanks!
I suggest to use a suffix pattern as URL pattern like *.jsf. If a Facelets file (.xhtml) is present on the given view ID, then it will be served. Otherwise if a JSP file (.jsp) is present on the given view ID, then it will be served. This also gives you the room to gradually upgrade from JSP to Facelets without the need to change URLs, so that you can ultimately get rid of those legacy JSPs in an easy way.
I'm currently upgrading an application from JSF 1.2 and Richfaces 3.3 to JSF 2 and Richfaces 4.
I'm having issues getting my application to include stylesheets using JSF2's new h:outputStylesheet component
Here is my old code:
<a4j:loadStyle src="resource:///com/testing/test/html/css/style.xcss" />
And here is what I have for my new code (Not working):
<h:outputStylesheet library="resource:///com/testing/test/html/css/" name="style.xcss" />
I've tried various variations but none have worked.
I get a message saying RES_NOT_FOUND when using firebugs css tab.
Any ideas?
Thanks
<h:outputStylesheet library="resource:///com/testing/test/html/css/" name="style.xcss" />
will not work for one reason - the library name is not the location of the resource, rather it is used to determine the location of the resource.
The manner in which the JSF runtime serves resources is detailed in the JSF 2.0 specification in chapter 2 titled "Request Processing Lifecyle". Resource handling is performed outside the confines of the usual Execute and Render lifecyle of JSF (that is used to service View requests). At runtime, a ResourceHandler associated with the Application is responsible for serving Resource requests.
The ResourceHandler uses a path based approach for looking up requests. The default implementation allows for resources to be placed in two locations:
In the Web-Application Root. Resources with identifier have to be placed in the /resources directory under the Web Application root, as /resources/<resourceIdentifier>.
In the Classpath. Resources with identifier must be present in the Classpath under the META-INF/resources directory, again as META-INF/resources/<resourceIdentifier>. In a web application, I've noticed that the directory should be the Web Application Root/WEB-INF/classes/META-INF/resources directory or a META-INF/resources directory under one of the directories in the parent classloader(s), or even in a JAR present in the Classpath. Apparently, the last option is the one undertaken by JSF 2 libraries/frameworks like PrimeFaces.
The JSF specification also specifies how the <resourceIdentifier> may consist of locales, library versions and resource versions, apart from the resource name itself. This is dealt with in a concise manner, in the ResourceHandler API documentation:
Packaging Resources
ResourceHandler defines a path based packaging convention for
resources. The default implementation of ResourceHandler must support
packaging resources in the classpath or in the web application root.
See section JSF.2.6.1 of the spec prose document linked in the
overview summary for the normative specification of packaging
resources.
Briefly, The default implementation must support packaging resources
in the web application root under the path
resources/<resourceIdentifier>
relative to the web app root.
For the default implementation, resources packaged in the classpath
must reside under the JAR entry name
META-INF/resources/<resourceIdentifier>
consists of several segments, specified as
follows.
[localePrefix/][libraryName/][libraryVersion/]resourceName[/resourceVersion]
None of the segments in the resourceIdentifier may be relative paths,
such as ‘../otherLibraryName’. The implementation is not required to
support the libraryVersion and resourceVersion segments for the JAR
packaging case.
Note that resourceName is the only required segment.
Going by the above, the following may work:
<h:outputStylesheet library="com/testing/test/html/css" name="style.xcss" />
provided that the stylesheet style.xcss is present in the directory structure com/testing/test/html/css located in either of the two areas mentioned above. Going by your need to place it outside the context root, the only possible option would be Web Application Root/WEB-INF/classes/META-INF/resources or any of the other suitable directory/JAR in the classpath (containing a META-INF/resources directory. This is of course, assuming that RichFaces does not provide it's own implementation of a ResourceHandler; if it does provide one, you should be looking at how it extends the default implementation to allow for resources to be placed elsewhere.
In Mojarra, the com.sun.faces.application.resource.ResourceHandlerImpl class extends the ResourceHandler class. ResourceHanderImpl uses the com.sun.faces.application.resource.ResourceManager class for finding resources. In turn, the ResourceManager delegates the loading of resources to the com.sun.faces.application.resource.WebappResourceHelper and com.sun.faces.application.resource.ClasspathResourceHelper classes. As their names imply, the former is responsible for looking up resources in the Web Application root, while the former is responsible for loading resources from the classpath. Going through these classes, one would find that failed attempts to load libraries get logged in the server's log; the RES_NOT_FOUND value is not generated by these classes, rather it is due to the renderer responsible for generating the page output.
I use jsf2 and richfaces4 with myeclipse 8.5
but i find it does not support those tags.
when i enter <h:head> and <h:form>
the ide show an error :
unknow resource
and i enter a4j: then press "alt" + "/", there is no prompt.
how can i config the ide?
Have you taken a look at JBoss Tools 3.2? It supports both JSF 2 and RichFaces 4 - JST/JSF 3.2.0.Beta2 What's New
The problem is probably that you are using the old jar files, which do not have those features. You should try it with new jar files.
Alternatively, the problem is you may have added two jars in lib folder or one in lib and the other is with capabilities.