Issues running my first JSF 2 application [duplicate] - java

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

Related

Running JSF pages by IntelliJ fails to work while HTML pages work correctly [duplicate]

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

security-constraint does not work

I need to block the direct access to the jsp pages.
I've set my web.xml like this:
<security-constraint>
<web-resource-collection>
<web-resource-name>My Hidden Pages</web-resource-name>
<url-pattern>/*.jsp</url-pattern>
</web-resource-collection>
<auth-constraint></auth-constraint>
</security-constraint>
but all the pages are still accessible by typing their address in the browser address bar.
How can I solve this?
FYI I'm using jetty-maven-plugin and servlet-api 2.5
thanks
You don't hide jsps that way.
There are a few common approaches (best choice first)
Precompile your JSPs during build time, and don't include the actual JSP files in your WAR file.
Put your JSP file in the WEB-INF folder somewhere. Access to the jsps are then done via a Controller servlet. This uses the security of WEB-INF to prevent direct access to the JSP files, something that all servlet containers must honor.
See past stackoverflow questions on this:
Why put JSP in WEB-INF?
How can I hide the JSP file in WEB-INF folder?
There are many more, just search for "jsp in web-inf" to discover more about this concept.
Properly configure Jetty's JSP implementation. Once done, this means all access to JSP files like must go through the that implementation's JspServlet.
See webdefault.xml for example of how this mapping is defined.
If you see an error or warning on startup about "No JSP Support for ", then you know you've not configured JSP properly, and that means all JSP files will instead be served in a static way.
Note: If you are using an older version of Jetty (anything older than version 7.6.16), or as using an older version of Java (anything older than 1.7_40), or are using Jetty on Windows (problem here is solved with Jetty 9.3.0 due out in the next month or so), then even this can be worked around.
Your <url-pattern> is incorrect. It should be <url-pattern>*.jsp</url-pattern> without the /. The allowed patterns according to spec are:
A URL pattern is a URI that is relative to the application context.
Patterns can include:
Path mapping, starting with / and ending with /* This pattern identifies any resource that starts with a given path, for example,
/catalog/* or /catalog/products/*
Extension mapping, starting with *. This pattern identifies any resource with the given extension, for example, *.jsp or *.gif
Default servlet mapping, containing only / This pattern identifies the default servlet of the application.
Exact matches This pattern uses a string that represents a specific resource, for example, /snoop is a servlet mapping and
/list/banner.jsp is a file mapping.
If you want to secure pages in given folder you need to use pattern like /folder/* , if you want to protect all pages use just *.jsp, if you want to protect all pages except index.jsp, you will need to add another constraint which allows explicitly access to the /index.jsp file.

JSF2.0 - *.xhtml pages give 404-NotFound but *.jsp work okay?

I have Weblogic 10.3.5 installed. I deployed the JSF 2.0 war on the server. In my WebContent folder, I have *.xhtml and *.jsp files, which contain JSF2.0 xhtml and pure JSP code, respectively. When I navigate to http://localhost:7001/MyApp/NewFile123.xhtml, I get a 404 Not found error page. (Nothing informative on the Eclipse console). But http://localhost:7001/MyApp/NewFile.jsp works well and does what it's supposed to do.
I am not mixing JSF and JSP but just wanted to see if JSP is gonna work. I have the appropriate servlet-mapping for the XHTML files.
I also have these on my classpath:
glassfish.el_1.0.0.0_2-2.jar
glassfish.jsf_1.0.0.0_2-1-5.jar
glassfish.jstl_1.2.0.2.jar
javax.servlet_1.0.0.0_2-5.jar
Another interesting thing, when I try to edit the *.xhtml files, the auto-complete doesn't work. (i.e it won't autocomplete <h:outp. It used to when I was using Weblogic 12.1 which has JSF2.0 out of the box.
Edit: Here is the relevant part of web.xml
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
So why do I get a 404 when I try to navigate to a JSF page? Any suggestions?
I also have these on my classpath:
glassfish.el_1.0.0.0_2-2.jar
glassfish.jsf_1.0.0.0_2-1-5.jar
glassfish.jstl_1.2.0.2.jar
javax.servlet_1.0.0.0_2-5.jar
Remove all those container-specific libraries from your /WEB-INF/lib. They do not belong there at all, the container already ships with them. Your /WEB-INF/lib should contain only the webapp-specific libraries which are not shipped with the container.
Your problem is most likely caused by the fact that Weblogic 1.0.3.5 is a Servlet 2.5 container which already ships with JSF 2.0, but that you're supplying a JSF 2.1 library which requires Servlet 3.0. I don't use Weblogic, but I've read that 1.0.3.x requires some specific steps to get JSF 2.0 to work, see also this blog. Here's an extract of relevance:
Download and install one of the latest Oracle WebLogic Server 11g Rel 1 (10.3.3) Installers from OTN. (Give the ZIP Installer a try. Aweseome lightweight!)
Create a new sample domain (call it whatever you want) and start the admin server
Open the administration console (http://localhost:7001/console/)
deploy the JSF 2.0 library (Deployments - Install - wlserver_10.3\common\deployable-libraries\jsf-2.0.war
Find your favorite JSF 2.0 sample (I'll take the guessNumber thing from the mojarra-2.0.2 distribution)
Add a weblogic.xml file to the WEB-INF/ folder with the following content:
<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app>
<library-ref>
<library-name>jsf</library-name>
<specification-version>2.0</specification-version>
<implementation-version>1.0.0.0_2-0-2</implementation-version>
<exact-match>true</exact-match>
</library-ref>
</weblogic-web-app>
Update as per the comments:
I now suspect that it may be because of the project settings. I created a Dynamic Web Project and chose JSF 1.2. On the next step, where it asked me for the JSF specification and implementation, I pointed him to those glassfish jsf2 jars. The default was 1.2. Maybe I shouldn't have done that?
That might have generated a JSF 1.2 compliant faces-config.xml which would force JSF 2.0 to run in JSF 1.2 modus. You need to redeclare the <faces-config> root declaration to comply JSF 2.0.
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">

Using .html files as JSPs

This may be a silly question but I've found no answer when googling this.
Currently, I map the requests from someFileName.html to a servlet which then forwards to someFileName.jsp using servlet mappings in web.xml. I would like to avoid that and just configure my application server so that html files are parsed and executed as if they were JSPs (so that custom tags and EL could be used from within the HTML). Bonus to answers that allow any extensions to be mapped to the JSP processor.
I use Tomcat but I'd like the solution to be portable to other containers such as Glassfish.
With 2 simple steps you can achieve this:
Add this servletmapping for the JSP servlet:
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
This tells the application container to use the the JSP servlet when serving html files.
Comment out the <mime-mapping> for text/html mime type (*.html) files so that the container won't handle HTML files as static content.
Hope this helps.

Java Page Rewriting

I am developing a java project.
I want to display an extention of any webpage as '.jsf' evenif it is 'jsp' or 'xhtml'.
What should I do?
Then just configure the FacesServlet accordingly?
<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
If you actually meant "I want to block direct access to *.jsp and *.xhtml so that the visitor is forced to invoke them by *.jsf", then add a security constraint to web.xml on the desired url-patterns and an empty auth-constraint:
<security-constraint>
<display-name>Restrict direct access to JSP and XHTML files</display-name>
<web-resource-collection>
<web-resource-name>JSP and XHTML files</web-resource-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.xhtml</url-pattern>
</web-resource-collection>
<auth-constraint />
</security-constraint>
Redirect all request to to the servlet that needs to handle the jsf requests
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>*</url-pattern>
</servlet-mapping>
STEPS (For new jsp project) :
In web.xml, change to *.jsf
Change to index.jsp
Create new welcome.jsp
In index.jsp page, include :
Run project and see extention in browser.
If this is for using JavaServer Faces, then the configuration of the JSF servlet enables the automatic mapping of .jsf to the underlying .xhtml or .jsp file.
I think you have it the wrong way round.
The user-agent will make requests to your servlet, with a given URI identifying the resource they wish to access. You decide what the correct URI for a given resource is, and how to respond to this request. So it's conceptually not a case of your webpage having an "address" that you want to display differently. Rather, it's a case of what URIs you want to use to map to which resources.
If you don't want to expose the extension, then you don't need URIs to have any extension at all, they're just strings. You will, however, need to think about how to resolve potential name clashes (as djna notes in the comment). I believe that this is configured for you at the Faces level, and actually BalusC's answer should have all the technical information necessary to do this.
I just wanted to point out the backwards nature of your thought processes, clearing this up will hopefully make it easier to grok the process in general. It's better that you understand it, than simply paste something into your web.xml that makes the problem go away (for now).
You should configure your server to process .jsf files as .jsp pages. How to actually do this depends on the server you are using - an information you haven't provided.
Disclaimer: I'm not familiar with either jsf or jsp, so I don't know what consequences this server modification will have on actual jsf pages.

Categories