I can't find in Internet any good explanation of mapping URLs in Java EE with JSF + managed bean (Yes - I know, that there are ten million of tutorials, but after reviewing first million with HelloWorld page I resigned of reading rest of them..).
Before reading about Java EE + JSF I was working with Spring + JSP project, where URL mapping was made with annotations #GET/#POST etc in controllers, with url as attribute - very easy solution with one method per one URL with putting resources to response page with method. (I don't know how it was made in background - I'm beginner, but solution was very easy :) )
Now I read a book about Java EE, there was something about mapping in web.xml file, but it was very unclear. I feel, that there is other thinking - JSF page while needs to be rendered is connecting to managed bean to obtain needed values. But how is the mapping done here?
It's probably not clean, so I'll explain with my sample.
I have the following structure of project
I want, that pages customerdetails.xhtml and customers.xhtml could be read with url localhost:8080/P1WSClient/customerdetails.xhtml and customers.xhtml respectively.
I've done the following web.xml configuration:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>Customers servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Customers servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
</web-app>
Ok, It's working. But how to make for example, when I want to make page customer to be loaded on default location localhost:8080/P1WSClient/ , or clients loaded on location localhost:8080/P1WSClient/something1/something2/mypage.html?
Other cuestion - why at the beginning url pattern is ´/faces/*.jsp´ and ´/faces/index/hxtml´? And index is being loaded on default url.. I don't get it!
Other cuestion - what is the thinging here - one ManagedBean per one page, or per one entity or.. ??
I can't find any good sample or tutorial, which could explain the urls mapping for many pages and many urls structure. If someone can explain mechanism of mapping in Java EE projects, please add it here. Any diagrams of mapping recognize with connection with managed beans and jsp inside app are also welcome :-)
If you want to change the default page (which is seen at localhost:8080/P1WSClient/) change the welcome file option in web.xml
<welcome-file-list>
<welcome-file>customers.xhtml</welcome-file>
</welcome-file-list>
If you want to reach a page under some directory, create folder in web-pages folder.
localhost:8080/P1WSClient/something1/something2/mypage.html
-Web Pages
--something1
----something2
-------mypage.xhtml
JSF requests go to the JSF servlet, which is the one in charge of locating the XHTML file, processing it and do the "work".
Sometimes the servlet is mapped to the all the URLs that end in .xhtml, other times only to the .xhtml URLs in a subdirectory. Of course, only requests that are mapped will be processed (if you have mapped the servlet to /faces/*.xhtml and you get a request for /myFiles/index.xhtml, the container will return index.xhtml as an static resource. As you understand, it could be any path, faces is just more usual.
I am not sure if how you can get the "redirect to some file if the URL does not specify one". I would try a Filter.
And for managed beans, it depends. Usually I am using one for the data and one for the controller of each page (data usually #ViewScoped, controller most times #RequestScoped), plus additional beans when needed for composite components.
Related
Ive been reading some posts about javax.faces.default_suffix but without success when trying to implement it.
Using : jsf 2.0, jboss 7.1, Mojarra 2.1.5
I need to show in URL the following : localhost:8080/myproject/index.jsf
when navigating also need show the xxx.jsf
web.xml
<welcome-file-list>
<welcome-file>/comum/inicio/index.xhtml</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern> **have tried *.jsf but with no success**
</servlet-mapping>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.jsf</param-value>
</context-param>
Would you help me on this issue please ? thanks
You're mixing the meaning of the default suffix and the URL pattern.
The javax.faces.DEFAULT_SUFFIX represents the default suffix of the physical file you've in your webapplication which represents a JSF file. This defaults in JSF 2.0 to .xhtml. If you change it to .jsf, then you should rename all physical files from some.xhtml to some.jsf. This makes generally no utter sense. You should not do that, just get rid of that context param altogether.
The <url-pattern> represents the default URL pattern which the enduser has to use in request URL in order to invoke the FacesServlet (which in turn uses the default suffix configuration to locate the physical file based on the URL). You said that you want to use *.jsf in URLs, however you have set it to *.xhtml. This is not right and changing the default suffix is not the right solution.
You should just set the URL pattern alone, not the default suffix.
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
This way http://localhost:8080/myproject/index.jsf will work.
Then there's a third problem: you're completely misunderstanding the purpose of the welcome file. It should not represent the path to the homepage. It should represent the filename of the physical file which you'd like to serve up as default file when a folder like /, /foo/, /foo/bar/, etc is requested. Just set it to index.jsf.
<welcome-file-list>
<welcome-file>index.jsf</welcome-file>
</welcome-file-list>
However, you should keep in mind that the container will verify the existence of the physical file before continuing the request, so that it can properly show a 404 error if absent. As *.jsf is actually a virtual URL, that step will fail. You can solve that by fooling the container by placing a physically existing but empty index.jsf file next to the index.xhtml file in the desired folder.
This way http://localhost:8080/myproject/ will work, provided that you have a real index.xhtml file and empty index.jsf file in the root folder.
Much easier is to just get rid of virtual URLs and stick to *.xhtml all the time.
See also:
JSF Facelets: Sometimes I see the URL is .jsf and sometimes .xhtml. Why?
JSF welcome file is not recognized
richfaces + index.xhtml having errors
This question already has an answer here:
JSF returns blank/unparsed page with plain/raw XHTML/XML/EL source instead of rendered HTML output
(1 answer)
Closed 5 years ago.
In Eclipse JUNO, I started:
new Dynamic Web Project
Name: JSFTest; Configuration: JavaServer Faces v2.0 Project
JSF Capabilites:
Copy jars to WEB-INF/lib (jstl-api, jstl-impl, jsf-api, jsf-impl):
new HTML to WebContent: index.xhtml with "New Facelet Composition Page", and the code inside:
in web.xml, I write the index.xhtml into the welcome part
when I run it on my apache tomcat 7 server, the result (don't bother about the h1 title):
So why doesn't it show the outtext and the button? What did I wrong? I saw a lot of video on youtube, I followed them, in the video it worked, but at me.
Because you have to access to the index.xhtml page under /faces/ virtual folder as stated in your web.xml file for the FacesServlet url mapping.
A simple way to make your JSF page to work is to change the url mapping in your web.xml
From:
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
To
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
If you don't want to change this, you must change your welcome-file to /faces/index.xhtml.
IMO it will be better the first option, in this way the FacesServlet will only process the xhtml pages, using the /faces/* will make it process any other resource as images, CSS and JS files.
I am new in JSF and EJB applications, hence I encounter problems even in the simple JavaEE applications. I am creating a simple JavaEE application in eclipse with JBoss with goal just to try some tags of JSF and the binding of them to Java Beans. I cannot find out why the following JSf code does not get nothing appear to the output page:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<f:loadBundle basename="resources" var="msg" />
<head>
<title><ui:insert name="pageTitle">Page Title</ui:insert></title>
<style type="text/css">
</style>
</head>
<body bgcolor="#ffffff">
<h:body>
<h:outputText value="#{hello.world}" />
<h:outputText value="TTT" />
</h:body>
</body>
</html>
Not only the value hello.world coming form Bean, but a simple text "TTT" does not appear as well. The code of the Bean is:
#ManagedBean
public class Hello {
final String world = "World";
/**
* Default constructor.
*/
public Hello() {
}
public String getWorld(){
return "Hello" + world;
}
}
The facelets-config.xml file is:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="2.1" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xi="http://www.w3.org/2001/XInclude"
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_1.xsd">
<managed-bean>
<managed-bean-name>hello</managed-bean-name>
<managed-bean-class>com.al.jsftest.Hello</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>
When I try the tag with a plain text, it comes out on the screen, but it does not work again with #{hello.world}, namely the binding to the Bean fails. As soon as I have a have I hint to how get the JSF tag give successfully output, I would appreciate hint regarding what I should take care of, in order to get the Bean bind to JSF?
UPDATE:
It seems to be the same problem with similar question, but my application is in Eclipse with JBoss, not in Netbeans with GlassFish. I add therefore my web.xml file, probably a modification in that is required, but I still cannot figure out it.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee /web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>JsfTest</display-name>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
<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>/faces/*</url-pattern>
</servlet-mapping>
You'll have to tell the server that your page should be loaded by the JSF-Servlet defined in your web.xml-file.
If I understand your sample right, you have a welcome file called index.xhtml which should be presented to the user with JSF by calling your website.
There is the problem:
All your pages won't be rendered by JSF unless you 'put them through' your defined JSF-Servlet.
Your servlet definition should look like this:
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern> /* !important */
</servlet-mapping>
And therefore you have two (there are more for sure :) ) ways to tell the server to load your page with the JSF-Servlet:
Tell your welcome-file to be loaded with the JSF-Servlet
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file> /* note the /faces/ prefix */
</welcome-file-list>
Extend your <url-pattern> inside the servlet-mapping
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
<url-pattern>*.xhtml</url-pattern> /*tell JSF to render all pages with xhtml-extension*/
</servlet-mapping>
Ther shouldn't be any difference between Netbeans+Glassfish and JBoss+eclipse but you should check if the JSF libraries are loaded by the server.
One last note:
You're configurating your Beans via faces-config.xml, that'll do the job but since JSF 2.x you're able to do the same inside your class via annotations, e.g.
#ManagedBean
#SessionScoped
public class TestBean {
// your stuff here
}
For me this is much easier and more readable.
Hope this helped, have Fun!
Edit:
After your comments I've tested your set-up: nothing wrong!
At first I've got an error because of the <f:loadBundle basename="resources" var="msg" /> which was not defined in my set-up but after deleting this line everything worked fine.
Nevertheless, I've made a small typo in my first list item so please check this again.
Your xhtml-skeleton looked fine for me and works in my test, so there shouldn't be anything wrong either.
Please check the following:
Are the JSF-libraries loaded either by the server or your application
Are there anymore Servlets defined inside your web.xml-file
What's the detailed error message
Cheers!
I created a new Dynamic Web Project and I added this time index.xhtml file using a "Blank Facelet Page" as template instead of "Common Facelet Page". I changed the url-pattern in my web.xml file as *.xhtml and it finally worked either by the full path name on the browser (\index.xhtml) or not. Following the same process with a "Common Facelet Page", I didn't manage to do it work. Strange.
I have also noticed, that after selecting "Common Facelet Page" and clicking next, a list of libraries appears and the user has the option to check some of them. I didn't check anything, maybe I should have.
I should use JSF 1.1 Mojarra implemetnation in job project.
But I need a popUp calendar widget. I've tried many different frameworks and stopped on tomahawk. I've setupped filter for tomahawk javasripts in web.xml but still have problems.
Should I necessary replace jsf-impl.jar and jsf-api.jar with myfaces-impl.jar and myfaces-api.jar ?
Or can I work with some versions of tomahawk calendar without faces.jar ?
Maybe someone can advice some popup calendar widget for JSF 1.1 from other frameworks that can be easy integrated?
Should I necessary replace jsf-impl.jar and jsf-api.jar with myfaces-impl.jar and myfaces-api.jar ?
No, that's not needed. Tomahawk is just a component library which is supposed to be JSF implementation independent. That it is created by the MyFaces guys is pure coincidence. I've used Tomahawk on Mojarra for ages and it works fine.
You should be more clear about those "problems" if you want more assistance. Ask a new question wherein you post the problem in depth detail (JSF/Tomahawk/Servletcontainer impl/version, steps done, unexpected results, any warnings/errors/exceptions, etc).
If you just need a date picker, you could use the pure javascript library, eg: http://www.nsftools.com/tips/DatePickerTest.htm
Seams that this combination works with JSF 1.1 Mojarra implementations:
commons-fileupload-1.2.2.jar
tomahawk-1.1.9.jar
And changes in web.xml:
<filter>
<filter-name>extensionsFilter</filter-name>
<filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>
</filter>
<!--
extension mapping for adding <script/>, <link/>, and other resource
tags to JSF-pages
-->
<filter-mapping>
<filter-name>extensionsFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
<!--
extension mapping for serving page-independent resources (javascript,
stylesheets, images, etc.)
-->
<filter-mapping>
<filter-name>extensionsFilter</filter-name>
<url-pattern>/faces/myFacesExtensionResource/*</url-pattern>
</filter-mapping>
i start with the programming of a JSF Website. At the moment all files have the .xhtml ending. When i go to http://localhost:8080/myProject/start.jsf everything is all right. But when i rename the file from start.xhtml to start.jsf i became a NoClassDefFound Error.
What is my mistake?
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
You have to change the javax.faces.DEFAULT_SUFFIX parameter (in web.xml)
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.jsf</param-value>
</context-param>
However, this is not advisable - either use .xhtml or .jsp for your files.
Note that you can use .jsp with facelets with no problems (if, for example the auto-complete of your IDE doesn't work for .xhtml).
Also note that:
the faces servlet mapping determines how the jsf pages are referred to from http perspective
the DEFAULT_SUFFIX parameter indicates what's the extension of the files.
Why do you want to rename the file start.jsf? The correct extension of the JSF files are .xhtml (but you can modify this default extension, as stated by Bozho).
In fact, to be precise, this extension is defined by Facelets (or JSF 2.0, as it natively integrate Facelets), which is different if you use "basic" JSP files.
It's best to stay with .xhtml because that's the right way to do it, but you can configure it with the javax.faces.DEFAULT_SUFFIX context-param in web.xml.