3

I need to change the context of my site by using parameter sended by client.

For example, if I call http://localhost:8084/JSF/ I load the usual index.xhtml with the "Homepage" page on the content template (as default). But, if I call http://localhost:8084/JSF/index.xhtml?page=profile, I need a sort of switch in the index.xhtml, and include/insert the profile template (or a page that define profile) in my content area.

I think i need to manage a servlet to do it, because i don't think i can create a sort of swith in my index.xhtml. So i think i need to load some template instead of another.

Which servlet i need to use? Or i need to create my own Servlet to do this?

Cheers

UPDATE (added after BalusC's suggestion)

package Beans;

import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ManagedBean;

@ManagedBean(name="selector")
@ManagedProperty(value="#{param.page}")
public class Selector {
    private String page;

    public String getPage() {
        return page;
    }

    public void setPage(String page) {
        this.page = page;
    }

}

template.xhtml

<?xml version='1.0' encoding='UTF-8' ?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html">

    <h:head>
        <title><ui:insert name="title">Facelets Template</ui:insert></title>
    </h:head>

    <h:body>
        <ui:insert name="login_homepage">Box Content Here</ui:insert>

        <ui:insert name="content_homepage">Box Content Here</ui:insert>
    </h:body>
</html>

index.xhtml

 <?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<ui:composition template="./template.xhtml"
                xmlns="http://www.w3.org/1999/xhtml"
                xmlns:ui="http://java.sun.com/jsf/facelets"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:f="http://java.sun.com/jsf/core">
    <ui:define name="title">
        // title
    </ui:define>

    <ui:define name="login_homepage">
        // login
    </ui:define>

    <ui:include src="#{selector.page}.xhtml" />

    <ui:define name="content_homepage">
        // content
    </ui:define>
</ui:composition>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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-app_2_5.xsd">
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>
    <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>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>faces/index.xhtml</welcome-file>
    </welcome-file-list>
</web-app>

profile.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets">
    <h2>PROFILE</h2>
</ui:composition>
markzzz
  • 47,390
  • 120
  • 299
  • 507
  • I added `jsf-2.0` and `facelets` as tags because I know based on your previous questions that you're using them. In the future, please add them yourself whenever applicable, because the answer would be completely different when you was using old JSF 1.x and/or JSP instead of Facelets. – BalusC Nov 24 '10 at 14:06

3 Answers3

9

Request parameters are settable in JSF bean by @ManagedProperty.

@ManagedProperty(value="#{param.page}")
private String page;

(this does basically a bean.setPage(request.getParameter("page")) directly after bean's construction)

You can use EL in Facelets <ui:include>.

<ui:include src="#{bean.page}.xhtml" />

(if bean.getPage() returns profile, the value would end up as profile.xhtml and included accordingly)

No need for legacy servlets :)


Update: you've set the annotation at the wrong place. It should look like this, exactly as in my original answer:

package beans;

import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean
@RequestScoped
public class Selector {

    @ManagedProperty(value="#{param.page}")
    private String page;

    public String getPage() {
        return page;
    }

    public void setPage(String page) {
        this.page = page;
    }

}

Note that I omitted the @ManagedBean name since the default value is already the classname with 1st character lowercased (which is exactly the same as you specified manually). I also added the @RequestScoped annotation to specify the bean scope. I also lowercased the packagename since uppercases are disallowed in package name as per standard Java Naming Conventions.

The whole <managed-bean> in faces-config.xml is entirely superfluous with the new JSF 2.0 annotations. You're basically duplicating it. Remove it.


Update 2: the index.xhtml should look like this

<!DOCTYPE html>
<html lang="en"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:c="http://java.sun.com/jsp/jstl/core">
    <h:head>
        <title>Include demo</title>
    </h:head>
    <h:body>
        <h1>This is the index page</h1>
        <c:catch>
            <ui:include src="#{selector.page}.xhtml" />
        </c:catch>
    </h:body>
</html>

(the <c:catch> is there to suppress the FileNotFoundException whenever there's no such file)

The include.xhtml should look like this:

<!DOCTYPE html>
<ui:composition 
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets">
    <h2>Include page content</h2>
</ui:composition>

Assuming that FacesServlet is listening on url-pattern of *.xhtml and the both files are in the same folder, open it by index.xhtml?page=include.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Tried to load page with some param value, but still doesnt work. Seems that web.xml have some troubles... – markzzz Nov 24 '10 at 14:27
  • Did you set the bean scope as well? It should be `@RequestScoped`. You omitted it in the question update, I've added it in my answer update. As to the `web.xml`, the minimum entry should be the `FacesServlet`, but this should be OK if other JSF pages works fine. It would only be problematic if you get `404 Resource not found` or `RuntimeException: cannot find FacesContext`. – BalusC Nov 24 '10 at 14:33
  • Uhm yes ive added it. But now seems that nothing work on my project. I renamed the package as you suggest (yes, my falut) and now nothing work. I'll try to do some test... arghh – markzzz Nov 24 '10 at 14:45
  • What's the `url-pattern` of the `FacesServlet`? Is it `*.xhtml`? If it is `*.jsf`, then you need to change it or to open the page by `index.jsf?page=profile` instead of `index.xhtml?page=profile`. Also, rightclick page in browser and *View Source* and verify if it contains NO SINGLE line of JSF/Facelets code. If there's JSF/Facelets code in the source in browser, then it means that the request URL didn't match the `url-pattern` of `FacesServlet` and thus `FacesServlet` isn't been invoked and thus all JSF/Facelets tags are left unprocessed and sent to browser as-is. – BalusC Nov 24 '10 at 14:47
  • Uhm yeah, but the problem is that the whole project doesnt do. For example my old function (login/ecc) doesnt work. Uhm...strange – markzzz Nov 24 '10 at 14:49
  • Ok now it works again. This method doesnt work... i'll post the whole code in few minuts :) – markzzz Nov 24 '10 at 14:53
  • Maybe your page composition was plain wrong. I added an example of both parent and include page. And please also elaborate "doesn't work" in more detail. What exactly happens and what exactly happens not? Elaborate in developer's perspective, not in enduser's perspective :) – BalusC Nov 24 '10 at 14:58
  • Yeah you are right. Forgives me, my english is not so brilliant :) – markzzz Nov 24 '10 at 15:06
  • I notice that the problem is, for example when i call the main page. If i call http://localhost:8084/JSF/ it load to me the portal. If i call http://localhost:8084/JSF/index.xhtml it show to me only content (but the source code is loaded on the browser. Just it doesnt show to me). Check on the topic the index.xhtml :) – markzzz Nov 24 '10 at 15:12
  • Then the `FacesServlet` is not mapped on `*.xhtml`. Maybe it's `*.jsf`. You should then replace URL in browser by `/index.jsf` or replace the `url-pattern` of `FacesServlet` in `web.xml` by `*.xhtml`. See also the 4th comment. By the way, best is to minimize noise in the code which you're going to post in the question. There is lot of code in your `index.xhtml` which is completely irrelevant to the *actual* question/problem. See for example my xhtml examples for a good example of the minumum necessary code related to the question. – BalusC Nov 24 '10 at 15:15
  • Thanks for the tips :) Ok, removed the irrelevant code and added the web.xml. With *.xhtml i get the 404 error! – markzzz Nov 24 '10 at 15:27
  • You've originally mapped the `FacesServlet` on `/faces/*`. You need to open it by `/faces/index.xhtml` instead (exactly as `` is doing!). This is however an old fashioned way (JSF 1.0 style) of mapping the `FacesServlet`. I'd suggest to use `*.xhtml` and don't put the files in the `/faces` folder. This way you will never face the problem of XHTML files being unparsed when not opening it by `url-pattern` of `FacesServlet`. – BalusC Nov 24 '10 at 15:29
  • Thats funny : I don't have their in /faces folder :) – markzzz Nov 24 '10 at 15:31
  • That was optional. But are you talking about 404 on `http://example.com` home page and not on `http://example.com/index.html`? If so, did you update the `` as well to remove `/faces`? – BalusC Nov 24 '10 at 15:33
  • Yes. In fact now work. Seems that NetBeans is crashed somewhere (after a recent updates). Wait, i restart my pc :) – markzzz Nov 24 '10 at 15:38
  • ok, now netbeans works better hehe! sorry. So, now works if i write also index.xhtml or index.xhtml?page=profile. Unfortunatly, it doesnt add the content of profile.xhtml. So there is a problem on my bean i think (in fact, if i call index.xhtml?page=profile it should print PROFILE, but it doesnt). I posted the profile.xhtml – markzzz Nov 24 '10 at 15:41
  • It works here. I've run the example as posted in my answer here. Your `index.xhtml` looks a bit odd anyway. I'd expect the `` and `` to be in `template.xhtml`. How does `template.xhtml` look like? How does it generated HTML in browser (*View Source*) look like? Anyway, try to run the exact example as in my answer. If it works, then this question is basically already answered and the cause of your current problem lies somewhere else. – BalusC Nov 24 '10 at 15:59
  • Don't know. I make a bit of order in my code, and i've also posted the template. Dunno why it doesnt work.. – markzzz Nov 24 '10 at 16:12
  • Right, you're using `ui:include` in an `ui:composition` for a `template`. This isn't going to work. Everything outside `ui:define` will be ignored. You need to put `ui:include` in an `ui:define` or inside `template.xhtml` instead. By the way, unrelated to the problem, the XML page declarations would only make MSIE havoc (so, remove them) and the doctype can nowadays better be the HTML5 one: ` `. See also [this answer](http://stackoverflow.com/questions/2935759/is-it-possible-to-use-jsffacelets-with-html-4-5). – BalusC Nov 24 '10 at 16:34
  • OHHH finally it works! Fine :) The last problem is that if i load the http://localhost:8084/JSF/ (or http://localhost:8084/JSF/index.xhtml) the Selector bean its not initialized, so i need to set "index" as default page...i think... – markzzz Nov 24 '10 at 16:36
  • You're welcome. Yes, you need to preset it. You can do it during property initialization `private String page = "index";` or in bean constructor `this.page = "index";`. *You also need to validate it since the enduser can change it manually by request parameter modification!* Alternatively, you can put `` in `` block and ignore the exception. I'll update the example in the answer. – BalusC Nov 24 '10 at 16:38
  • Yeah i tried. Unfortunatly this doenst work (or better, it said Invalid path : .xhtml :)); but i think it depends to the eager attribute on @ManagedBean? – markzzz Nov 24 '10 at 16:42
  • Fine. A intelligent "workaround" :) Unfortunatly, for some reason, i need to initializate the index.xhtml as first page... i'll try to do some. Thanks again for your time (some hours to resolve this problem, hehe). You rock!!! – markzzz Nov 24 '10 at 16:50
  • 1
    It was per saldo only about 15 minutes :) But when I come to Italy, I deserve a beer! – BalusC Nov 24 '10 at 16:57
  • Yeah of course :) Hahah! As last problem, still the trouble that i can't initalizate homepage as "default" page...uhm... – markzzz Nov 24 '10 at 17:04
0

In the updated question, the following lines are out of order:

@ManagedBean(name="selector")
@ManagedProperty(value="#{param.page}")
public class Selector {
    private String page;

It should be this:

@ManagedBean(name="selector")
public class Selector {
    @ManagedProperty(value="#{param.page}")
    private String page;
hibbelig
  • 510
  • 6
  • 15
0

The problem is that if you have a commandButton in the dynamically included file, the commandButton won't work. The action routine is never called. I am still trying to find a solution to this, even with Mojarra 2.1.

Oversteer
  • 1,778
  • 1
  • 22
  • 38