2

I have a JSF 2.0 project that I am unable to obtain a FaceletContext from.

Here is the setup from my 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>
<context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
</context-param>

<context-param>
    <param-name>facelets.DEVELOPMENT</param-name>
    <param-value>true</param-value>
</context-param>

<context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>server</param-value>
</context-param>

<context-param>
    <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
    <param-value>false</param-value>
</context-param>

<context-param>
    <param-name>javax.faces.FULL_STATE_SAVING_VIEW_IDS</param-name>
    <param-value>/index.xhtml</param-value>
</context-param>
<context-param>
    <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
    <param-value>.xhtml</param-value>
</context-param>

<context-param>
    <param-name>javax.faces.application.CONFIG_FILES</param-name>
    <param-value>/WEB-INF/faces-config.xml</param-value>
</context-param>

<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
</servlet-mapping>

I can obtain the FacesContext, but not the FaceletContext. The following lines of code are where the issue lies:

            FacesContext fctx = FacesContext.getCurrentInstance(); //works
    //FaceletContext f2ctx = (FaceletContext) fctx.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
    FaceletContext f2ctx = (FaceletContext) fctx.getELContext().getContext(FaceletContext.class);

Can anyone assist?

Update:

The above was a snippet from my overall goal: loading a facelet file containing a dialog on demand, then add it to a parent to display. The code below is incomplete, but should explain what I'm getting at. Note that the app uses the Primefaces library, hence the RequestContext object.

public void launch() {

    form.getChildren().clear();

    FacesContext fctx = FacesContext.getCurrentInstance();
    for (Object o: fctx.getAttributes().keySet()) {
        System.out.println(o.toString());
    }

    FaceletContext f2ctx = (FaceletContext) fctx.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
    //FaceletContext f2ctx = (FaceletContext) fctx.getELContext().getContext(FaceletContext.class);
    dialog = new Dialog();

    try {
        f2ctx.includeFacelet(dialog, "/WEB-INF/facelets/dialog/manager.xhtml");
        form.getChildren().add(dialog);
    } catch (IOException ex) {
        log.debug(ex.toString());
    }

    RequestContext.getCurrentInstance().update("mainPageCenterForm");
}
Jason
  • 3,943
  • 12
  • 64
  • 104

1 Answers1

1

It will be null when you try to access it before the view is ever been built. For example, during the beforePhase of RESTORE_VIEW phase. Rearrange your code logic. It's not clear what's the functional requirement is and where exactly you're trying to access it, so I can't give a more suited answer.


Unrelated to the concrete problem, the javax.faces.FULL_STATE_SAVING_VIEW_IDS context param is ignored when the partial state saving is disabled. Perhaps that was not your intent? See also this related answer Should PARTIAL_STATE_SAVING be set to false?

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks for pointing out that issue, it was leftover from some experimenting. I added the full method and an explanation of what I'm trying to do. Unfortunately, I cannot use a dynamic ui:include to do what I need. – Jason Apr 26 '12 at 18:24
  • When exactly is `launch()` called? What do you get when you debug/print `FacesContext#getViewRoot()` and `FacesContext#getCurrentPhaseId()`? – BalusC Apr 26 '12 at 18:31
  • I'm seeing your point about why it's null. The launch method is being called as an action in a Primefaces MenuItem, but that is defined on another page (index.xhtml). However, the app is dialog-heavy (customer requirement), so I'm trying to figure out how to do a load on demand for the relevant Facelet. – Jason Apr 26 '12 at 18:37
  • Try `` straight in the view instead. – BalusC Apr 26 '12 at 18:39
  • FacesContext#getViewRoot() returns a UIComponentBase, and getCurrentPhaseId() returns "INVOKE_APPLICATION" – Jason Apr 26 '12 at 18:40
  • Well, I'd expect it to return non-null then. What JSF impl/version and PrimeFaces version exactly? Or wait, is it an ajax request? – BalusC Apr 26 '12 at 18:41
  • JSF is glassfish jsf 2.0 as provided by Weblogic server, and Primefaces is 3.2. – Jason Apr 26 '12 at 18:43
  • I don't have Weblogic at hands now, but all I can tell based on earlier problems/questions I've read before is that it's a rather odd beast. Have you already given the expliciet view markup with `` a try? – BalusC Apr 26 '12 at 18:45
  • I haven't done that yet. Question: will the ui:include be processed regardless, but only rendered when the condition becomes true? Or will the ui:include only "trigger" once that condition is true? – Jason Apr 26 '12 at 18:47
  • It will be processed during view build time regardless. You could use `` instead. But this may have another undesireable side effects. – BalusC Apr 26 '12 at 18:48
  • Okay, that's what I'm trying to avoid, since the application is dialog heavy, but a given user may only use a few of those dialogs during a given session. I might try switching over to Mojarra 2.0 and see if there is a difference. – Jason Apr 26 '12 at 18:50
  • I just did a quick test with Mojarra 2.1.7 on Tomcat 7.0.26 and Glassfish 3.1.1 and it returns non-null to me. – BalusC Apr 26 '12 at 18:52
  • You're fortunate... I had no luck. Guess I'll try tomcat next just to see if it's Oracle's usual policy of making life miserable for developers. – Jason Apr 26 '12 at 19:43
  • Nope, same error on Tomcat. Might have to figure out a different way to do this. – Jason Apr 26 '12 at 19:53
  • 1
    In Myfaces, some good hacks were done to solve the problems over ui:include / c:if . It is better to let facelets build the component tree, so if you can, it is better to use template tags or a composite component. Try to change the component tree outside facelets (on the managed bean) works too, but that causes problems later when the view is refreshed, and increase the state size without need. – lu4242 Apr 26 '12 at 20:05
  • Moved this to a new question, http://stackoverflow.com/questions/10353381/unable-to-reference-faceletcontext-in-a-managed-bean – Jason Apr 27 '12 at 15:24