Am I using the action of pretty faces configuration correctly? Advice needed!

Splash Forums PrettyFaces Users Am I using the action of pretty faces configuration correctly? Advice needed!

Tagged: ,

This topic contains 11 replies, has 3 voices, and was last updated by  Christian Kaltepoth 4 years, 6 months ago.

Viewing 12 posts - 1 through 12 (of 12 total)
  • Author
    Posts
  • #18888

    DevySqueesy
    Member

    Hi My friends,

    Recently, I have run into an issue in my application. The more I think, the more I feel myself might have used the framework in a wrong way. Any advices would be appreciated.

    Application background

    We use pretty faces to map SEO URLs to the actual xhtml file. We also use action to call a method in the controller which builds a bean for xhtml to use. The bean has template name and other content for use at render time. This way, we achieved the capability of dynamically applying a JSF template. In the code below, the pageInfo.templateName tells the template to use.

    <ui:composition template="/resources/templates/#{pageController.pageInfo.templateName}.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:jawr="https://jawr.dev.java.net/jsf/facelets">
    ......
    </ui:composition>

    Problem I am facing

    The above pattern works well until I want to put a form on the page.

    When I have a page which containers a form, the capability is broken when the form is POSTED to the server. According to the JSF life cycle, the first phase is restore view. The problem I had was the restore view phase did not resolve the correct template name. I found out that it was because the pageInfo bean was not initialized. Further research tells me that the prettyfaces phase listener is executed after restore view phase. That’s why pageInfo is not built yet.

    Temp solution

    In PageController, I had a null check in the getter. If the pageInfo bean is not built, I will explicitly build it and make it available. Would this be conflict with the action of prettyfaces?

    I would like to have Lincoln or any expert here to review my solution. Any advice is appreciated.

    #23146

    Hmmm… this is an unfortunate reality of the JSF lifecycle. PrettyFaces generally cannot operate before restore view because it’s possible that certain bean scopes are not active (which would cause exceptions since actions and injections wold fail.)

    What you are doing is fine and should not conflict with PrettyFaces, but I do wonder if it’s possible to solve this problem another way, in PrettyFaces itself. I’ll have to think about it. For now what you are doing is just fine! :)

    ~Lincoln

    #23147

    DevySqueesy
    Member

    Thank you Lincoln.

    Another approach I have done is to always build the bean in a method with @PostConstruct annotation. This way, I completely do not need action anymore.

    Maybe this question should be asked in a this way. What is the purpose of having action in prettyfaces? What’s the author’s intention? I would like to know it and in future apply the capability.

    #23148

    The intent of action methods is to provide a ‘front-controller’ style programming model to JSF. There are of course other ways of achieving the same functionality (as you have described,) and all options are valid :) But if you prefer to define actions and outcomes in one place, then action methods are for you.

    They can also be helpful for JSF environments where @PostConstruct is not honored or available (for instsance, older JSF1.1 and 1.2 versions where more advanced bean containers were not available.)

    Hope this helps :)

    ~Lincoln

    #23149

    Also, action methods let you navigate to a new location much more a much more declarative fashion, simply return a JSF navigation string. This is something you cannot do from a getter or from a @PostConstruct method. You are also guaranteed to know when the method is being executed, and in which lifecycle, instead of guessing when your bean is instantiated or accessed.

    #23150

    DevySqueesy
    Member

    Great Answer! Thank you very much Lincoln.

    #23151

    Hey all,

    I want to add one more argument for PrettyFaces action methods. IMHO the really nice thing is that they are executed AFTER path or query parameters are injected into you bean (if you are using EL-injection for your parameters). So they can be used for any kind of initialization that requires something from the URL. You won’t get this with @PostConstruct.

    Christian

    #23152

    DevySqueesy
    Member

    I got your point. I do find this is very unfortunately that I will need special handling for path variables and query parameters in the restore view phase.

    #23153

    DevySqueesy
    Member

    Hi Lincoln,

    If you have any idea about resolving this issue in prettyfaces, please let me know.

    #23154

    If I understood you correctly. your current problem is that the path parameters are injected after restore view instead of before restore view. One possible way to work around this issue is to use named path parameters instead of EL-injected ones. Named path parameters are immediately available using the standard Servlet API while EL-injected parameters are injected after restore view.

    Have a look at this part of the documentation:

    http://ocpsoft.org/docs/prettyfaces/3.3.3/en-US/html/Configuration.html#config.pathparams

    And especially:

    http://ocpsoft.org/docs/prettyfaces/3.3.3/en-US/html/Configuration.html#config.pathparams.named

    #23155

    DevySqueesy
    Member

    Hi Christian,

    My problem is the path to the template is not available until the action method of the controller is called. The invoke of the method is not happening until the pretty faces listener kicks in after restore view phase. It makes it impossible to restore the view on POST back. This is my challenge currently.

    #23156

    My idea was that you could do something like this:

    <url-mapping ...>
    <pattern value="/page/#{ template }/whatever" />
    ....
    </url-mapping>

    And:

    @ManagedBean
    @RequestScoped
    public class PageController {

    @PostConstruct
    public void init() {
    HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
    String templateName = request.getParameter("template")
    // create pageinfo stuff
    }

    }

    This way you could use a method annotated with @PostConstruct to do the initialization. This will be done when the bean is first accessed, even if it is before RESTORE_VIEW.

Viewing 12 posts - 1 through 12 (of 12 total)

You must be logged in to reply to this topic.

Comments are closed.