Create a link to a JSF page in a subfolder - jsf

I have a Java web app with the following structure:
- Project
- Web Pages
+ WEB-INF
+ resources
- administration
systemsettings.xhtml
userhandling.xhtml
login.xhtml
index.xhtml
menubar.xhtml
...
+ Source Packages ...
I recently added the administration folder to the Web Pages, and I moved there the two .xhtml pages so I can write more specific URL pattern for my administrator authorization filter.
However, I don't know what is the path for the pages in the administration folder. While <a href='index.xhtml'> works, <a href='administration/systemsettings.xhtml'> doesn't, throws java.io.FileNotFoundException.
Update:
The content of the systemsettings.xhtml was:
<h:body>
<ui:insert name="header" >
<ui:include src="menubar.xhtml" />
</ui:insert>
<div>Administration - System settings</div>
</h:body>
I forgot to update the path to the included page, after the refactor. This can be fixed, as #BalusC suggested, by changing the <ui:include src="menubar.xhtml" /> to <ui:include src="/menubar.xhtml" />.

If a link does not start with a scheme like http://, then it's a relative link which is relative to the current request URI as you see in browser's address bar. If a relative link starts with /, then it's relative to the domain root in request URI. If a relative link does not start with / then it's relative to the currently opened folder in request URI.
If you can't tell about the currently opened folder for sure, then you need to make it a domain-relative link by explicitly prepending the context path as available by #{request.contextPath}.
settings
An alternative is to just use JSF <h:link> component. It will automatically prepend the context path (and also automatically apply the JSF mapping!). The following <h:link> examples generate equivalent HTML.
<h:link value="settings" outcome="/administration/systemsettings.xhtml" />
<h:link value="settings" outcome="/administration/systemsettings" />

Related

Issue with h:form - Returning 404 when submitting through h:commandbutton

I am working on a JSF (2.2) application. I am seeing some weird behavior working with h:form and h:commandbutton.
Issue - I have following code in say searchRecord.xhtml -
<h:form>
<!-- Input fields -->
<h:commandbutton type="submit" value="Search" title="Search" action="#{bean.search}"/>
</h:form>
The issue I am facing is when I click on submit button, it shows 404-page not found with URL pointing to current page. It is not executing the specified bean action.
I tried to debug this. When the form is getting translated into HTML, the form is getting generated with method="post" action="/MyApplication/WEB-INF/searchRecord.xhtml" (which looks to be the correct behaviour). Still, on clicking the button, I am getting 404.
Can anyone please help me figuring out what is the issue? I wasted my weekend figuring this out but in vain.
EDIT -
IDE - Eclipse
JSF Version - Mojarra 2.2.8
Directory structure of my project is -
Project
- Java Resource
----src -> contains java files
- WebContent
---- META-INF
---- WEB-INF
------facelets -> contains *.xhtml files
------resources -> contains img, css and JS files in respective folders
------commonLayout.xhtml
- index.xhtml
I access my application using a launchHandler servlet which validates the request parameters and forward to searchRecord.xhtml.
I am able to see searchRecord.xhtml. but Now when I click , I am getting 404.
As a standard, we are required to use servlet and then forward accordingly.
I found solution for my problem. The issue here was the wrong directory structure (Somehow I missed the point that resources under /WEB-INF are not reachable by URL. Thanks to #BalusC for pointing this out!!!). Based on the answers on below post -
JSF files inside WEB-INF directory, how do I access them?
Which XHTML files do I need to put in /WEB-INF and which not?
I restructured my projects as follows -
My Application
|- Java Resource
|----src -> contains java files
|- WebContent
|---- META-INF
|---- Resources -> contains img, css and JS files in respective folders
|---- JSF
| |--Contains client .xhtml files
|---- WEB-INF
| |--template -> contains the master templates for my application
| |--web.xml
|---- index.xhtml
Now the navigation is happening as expected and all the pages are displayed.
I am also planning to use JSF 2.2 configuration parameter and put resources under WEB-INF.

OmniFaces CDNResourceHandler could not find resources when not included locally

I'm using OmniFaces CDNResourceHandler to point my resources to a CDN, instead of local files.
I added this line in my XHTML file: <h:outputStylesheet library="twitter-bootstrap" name="bootstrap.min.css" />
And my faces-config.xml have this line:
<context-param>
<param-name>org.omnifaces.CDN_RESOURCE_HANDLER_URLS</param-name>
<param-value>
twitter-bootstrap:bootstrap.min.css=https://somehost/twitter-bootstrap/3.3.7/bootstrap.min.css
</param-value>
</context-param>
And I'm getting this error when access the page:
Unable to find resource twitter-bootstrap, bootstrap.min.css
Note: When I access the file at https://somehost/twitter-bootstrap/bootstrap.min.css I can download the file properly.
I'm using Mojarra under Wildfly configured to Development stage.
The resource handler is properly configured at faces-config.xml file.
<application>
<resource-handler>org.omnifaces.resourcehandler.CDNResourceHandler</resource-handler>
</application>
I did some tests, and I notice that the error doesn't occurs if I create an empty file bootstrap.min.css under WEBAPP_FOLDER/resources/twitter-bootstrap. If I delete the file, the errors occurs again.
Even I use CDN, do I need to keep resources locally?
The CDNResourceHandler is primarily intented to move auto-included JSF resources to a CDN, such as jsf.js file from <f:ajax>, or primefaces.js and jquery.js from PrimeFaces, or to automatically switch to a CDN when installed in production.
You don't need it in your case with a permanent CDN resource. Just use plain <link>.
<link rel="stylesheet" src="https://somehost/twitter-bootstrap/bootstrap.min.css" />
This is also explicitly mentioned in the CDNResourceHandler documentation.
For non-JSF resources, you can just keep using plain HTML <script> and <link> elements referring the external URL
Update: as you're not the first one who wondered about this, I've as per issue 122 bypassed this technical restriction for OmniFaces 2.6. In other words, you do not necessarily need a local resource anymore.

JSF preRenderView not triggered when navigating to page without using Redirect

I have created a preRender method to be called when the user navigate to that specific page, I use:
<f:metadata>
<f:event listener="#{targetClass.prerender()}"
type="preRenderView">
</f:event>
</f:metadata>
but the problem is that this method is not being called when I navigate to this page, unless I use
<redirect />
in the faces-config.xml file.
But, I don't want to use redirect, so the url always point to the login page.
Thank you.

How can I output a favicon <link> in the HTML head section using JSF 2.0?

Using h:outputStylesheet I can embed CSS resources in the HTML head section, but how can I build a <link> for a favicon image resource which renders HTML like in this example:
HTML output:
<head>
...
<link rel="icon" type="image/png" href="favicon.png" />
...
</head>
The image resource is located in <web>/resources/images.
If I use direct HTML code in the JSF template like href="/resources/images/favicon.png" the resource is not found - navigating to /resources/images/favicon.png leads to the error
/resources/images/favicon.png/index.jsf
not found
(I have set index.jsf as index page in web.xml which might explain this path)
Your webapp is apparently running on a non-empty context path. The leading slash / brings you to the domain root. Use #{request.contextPath} to dynamically inline the context path.
<link rel="shortcut icon" type="image/png" href="#{request.contextPath}/resources/images/favicon.png" />
(note that I fixed the rel as well to make it crossbrowser compatible)
The href="/resources/images/favicon.png" is actually looking in the root direcotry of your server http://localhost/resources/images/favicon.png and not inside your web application directory.
Your href location will need to include the web application directory href="/webappname/resources/images/favicon.png" http://localhost/webappname/resources/images/favicon.png
If your .xhtml file is in the same directory as your resources folder then removing the forward slash at the being should work as well.
href="resources/images/favicon.png"

jsf navigation question

I have a JSF2 project with a "view user" page that reads the currently selected user from a session bean; userHandler.selectedUser.
The page is intended to be visited by navigating with links in the app.
However, if the user attempts to hit the "view user" page directly by this URL ...
http://localhost:8080/webapp/userView.jsf
... they see the page with no data on it (because there's no selected user in the userHandler).
I think what I'd like to do is redirect the user to the main page of the app if they try to hit it directly like that. What is a simple and elegant way of handling this problem?
Thanks,
Rob
You'd like to hook on the preRenderView event and then send a redirect when this is the case.
<f:metadata>
<f:event type="preRenderView" listener="#{bean.preRenderView}" />
</f:metadata>
with
public void preRenderView() throws IOException {
if (userHandler.getSelectedUser() == null) {
FacesContext.getCurrentInstance().getExternalContext().redirect("home.jsf");
}
}
A way to avoid this problem from the start is to have pages that you don't want to be accessed directly via URL into the WEB-INF folder of your project.
This way, your pages aren't accessible directly via URL.

Resources