This discussion is archived
12 Replies Latest reply: Oct 22, 2012 10:31 PM by r035198x RSS

Sessions and Controllers best-practice in JSF2

jmsjr Newbie
Currently Being Moderated
Hi,

I've not done web development work since last using Apache Struts for its MVC framework ( about 6 years ago now ). So bear with me if my questions does not make sense:

SESSIONS

1) Reading through the JSF2 spec PDF, it mentions about state-saving via the StateManager. I presume this is also the same StateManager that it used to store managed-beans that are in @SessionScoped ?

2) In relation to session-scoped managed beans, when does a JSF implementation starts a new session ? That is, when does the implementation such as Mojarra call ExternalContext.getSession( true ) .. and when does it simply uses an existing session ( calling ExternalContext.getSession( false ) ) ?

3) In relation to session-scoped managed beans, when does a JSF implementation invalidate a session ? That is, when does the implementation call ExternalContext.invalidateSession() ?

4) Does ExternalContext.getSession( true ) or ExternalContext.invalidateSession() even make sense if the state-saving mechanism is client ? ( javax.faces.STATE_SAVING_METHOD = client ) Will the JSF implementation ever call these methods if the state-saving mechanism is client ?


CONTROLLERS

Most of the JSF2 tutorials that I have been reading on-line uses the same backing-bean when perfoming an action on the form ( when doing a POST or a GET or a post-back to the same page ).

Is this best practice ? It looks like mixing what should have been a simple POJO with additional logic that should really be in a separate class.
What have others done ?
  • 1. Re: Sessions and Controllers best-practice in JSF2
    EJP Guru
    Currently Being Moderated
    1) Reading through the JSF2 spec PDF, it mentions about state-saving via the StateManager. I presume this is also the same StateManager that it used to store managed-beans that are in @SessionScoped ?
    Same thing and same process. Not that you to have anything to do with the StateManager yourself directly, it just happens according to your scope annotations.
    2) In relation to session-scoped managed beans, when does a JSF implementation starts a new session ?
    When it needs a session to attach a session scope to and there isn't one already. In reality the servlet container creates sessions. Your application can too.
    3) In relation to session-scoped managed beans, when does a JSF implementation invalidate a session ? That is, when does the implementation call ExternalContext.invalidateSession() ?
    Only when you do, or maybe during teardown or reload.
    4) Does ExternalContext.getSession( true ) or ExternalContext.invalidateSession() even make sense if the state-saving mechanism is client ?
    Certainly, why not?
    Will the JSF implementation ever call these methods if the state-saving mechanism is client ?
    I don't see what difference it makes.
    Most of the JSF2 tutorials that I have been reading on-line uses the same backing-bean when perfoming an action on the form ( when doing a POST or a GET or a post-back to the same page ).

    Is this best practice?
    I'm not convinced that it is.
    It looks like mixing what should have been a simple POJO with additional logic that should really be in a separate class.
    I agree.
    What have others done ?
    My own practice is to write as few POJOs as possible, preferably none, and to put form actions where they belong functionally, rather than insist on a backing bean per page. For me a POJO class is one of the most pointless things on the planet.
  • 2. Re: Sessions and Controllers best-practice in JSF2
    jmsjr Newbie
    Currently Being Moderated
    EJP wrote:
    1) Reading through the JSF2 spec PDF, it mentions about state-saving via the StateManager. I presume this is also the same StateManager that it used to store managed-beans that are in @SessionScoped ?
    Same thing and same process. Not that you to have anything to do with the StateManager yourself directly, it just happens according to your scope annotations.
    2) In relation to session-scoped managed beans, when does a JSF implementation starts a new session ?
    When it needs a session to attach a session scope to and there isn't one already. In reality the servlet container creates sessions. Your application can too.
    When it the lifecycle of a JSF request ( which Phase in terms of PhaseEventListener) does the implementation creates a new session ?
    I guess my question is:

    * Should I let the implementation create the session for me ? ... or
    * Should I create one myself before the implementation does it ?

    I know I can do either .. but what is best ?
    I think the answers to the question above also depends on / or is related to when the implementation creates a new session.

    In the old days of Struts, I ( the webapp developer ) control when sessions are created and when sessions are invalidated. Now that the implementation is possibly creating a new session behind the scene, I think I need to know when it is created, so that I don't create another one ( .. or maybe getSession( true ) returns the same session if one already exists anyway ... been awhile I know ).

    I can't find in the spec PDF where it says that the implementation must create a session on THAT phase of the lifecycle if one does not exist yet.

    Thanks for the response.
  • 3. Re: Sessions and Controllers best-practice in JSF2
    EJP Guru
    Currently Being Moderated
    When it the lifecycle of a JSF request ( which Phase in terms of PhaseEventListener) does the implementation creates a new session ?
    I've been using JSF for several years and I've never needed to know the answer. What difference can it possibly make to you what phase it happens in?
    I guess my question is:

    * Should I let the implementation create the session for me ? ... or
    Certainly.
    * Should I create one myself before the implementation does it ?
    Only if you need it first. When exactly would that actually happen?
    I know I can do either .. but what is best ?
    I don't see any reason to do anything that the platform software will already do for you.
    I think the answers to the question above also depends on / or is related to when the implementation creates a new session.
    I don't see why.
    maybe getSession( true ) returns the same session if one already exists anyway
    Yes it does. It just ensures that a session exists. Where getSession() can return a null, getSession(true) cannot.

    I think you're creating problems where they don't exist. I get the session when I need it, which is very rare; I never call getSession(true); and I call invalidate() when they press the Logout button. That's all I've ever needed.
    I can't find in the spec PDF where it says that the implementation must create a session on THAT phase of the lifecycle if one does not exist yet.
    I can't think of a reason why it would specify it at all. All it really does is call HttpServletRequest.getSession(true) at various points when it needs to play with the session scope. That could happen in any phase at all.
  • 4. Re: Sessions and Controllers best-practice in JSF2
    jmsjr Newbie
    Currently Being Moderated
    EJP wrote:
    When it the lifecycle of a JSF request ( which Phase in terms of PhaseEventListener) does the implementation creates a new session ?
    I've been using JSF for several years and I've never needed to know the answer. What difference can it possibly make to you what phase it happens in?
    I can't find in the spec PDF where it says that the implementation must create a session on THAT phase of the lifecycle if one does not exist yet.
    I can't think of a reason why it would specify it at all. All it really does is call HttpServletRequest.getSession(true) at various points when it needs to play with the session scope. That could happen in any phase at all.
    Thanks again.
    Not really a good example, but:

    If I am writing a class implementing PhaseListener, and perhaps interrogating the HttpSession for a bean that was supposed to be added into the session because it was @SessionScoped, but if the @SessionScoped managed bean is only added to the session at .. Phase.UPDATE_MODEL_VALUES .. .and my PhaseListener was for the Phase.PROCESS_VALIDATIONS, then I am returning the wrong Phase in getPhaseId() as PROCESS_VALIDATIONS happens before UPDATE_MODEL_VALUES.
  • 5. Re: Sessions and Controllers best-practice in JSF2
    EJP Guru
    Currently Being Moderated
    If I am writing a class implementing PhaseListener, and perhaps interrogating the HttpSession for a bean that was supposed to be added into the session
    Then you would be doing it wrong. The correct way to get the bean is via evaluation of an EL, which you can do via the API, something like this:
    FacesContext context = FacesContext.getCurrentInstance();
    ELContext elContext = context.getELContext();
    ValueExpression ex = context
                             .getApplication()
                             .getExpressionFactory()
                             .createValueExpression(elContext,
                             "#{directory}", DirectoryBean.class);
    directoryBean = (DirectoryBean) ex.getValue(elContext);
  • 6. Re: Sessions and Controllers best-practice in JSF2
    jmsjr Newbie
    Currently Being Moderated
    EJP wrote:
    If I am writing a class implementing PhaseListener, and perhaps interrogating the HttpSession for a bean that was supposed to be added into the session
    Then you would be doing it wrong. The correct way to get the bean is via evaluation of an EL, which you can do via the API, something like this:
    FacesContext context = FacesContext.getCurrentInstance();
    ELContext elContext = context.getELContext();
    ValueExpression ex = context
                             .getApplication()
                             .getExpressionFactory()
                             .createValueExpression(elContext,
                             "#{directory}", DirectoryBean.class);
    directoryBean = (DirectoryBean) ex.getValue(elContext);
    Again, thanks for that. Now I know I can do it via EL .. but .. how is using something like:

    DirectoryBean directoryBean = (DirectoryBean) FacesContext.getExternalContext().getSessionMap().get("directory" );

    any different or wrong than using EL ? Why is using EL "better" or "correct" than simply using:

    FacesContext.getExternalContext().getSessionMap().get(<beanName>) ?

    .. if I am specifically expecting the bean to be in session-scope ? Am I missing something ?
  • 7. Re: Sessions and Controllers best-practice in JSF2
    EJP Guru
    Currently Being Moderated
    It's better because it ensures the bean gets instantiated, stuck in the session, which gets instantiated itself, the bean gets initialised, resource-injected, etc etc etc. Your way goes goes behind the scenes and hopes for the best, and raises complicated questions that don't really need answers.
  • 8. Re: Sessions and Controllers best-practice in JSF2
    jmsjr Newbie
    Currently Being Moderated
    EJP wrote:
    It's better because it ensures the bean gets instantiated, stuck in the session, which gets instantiated itself, the bean gets initialised, resource-injected, etc etc etc. Your way goes goes behind the scenes and hopes for the best, and raises complicated questions that don't really need answers.
    Thanks.

    1) But if I only want to check that the bean is in the session ... and I do NOT want to create an instance of the bean itself if it does not exist, then I presume I should still use ExternalApplication.getSessionMap.get(<beanName>).

    2) But If I want to instantiate a bean if it does not exist in the session, and do all the injection, from within PhaseListener, then I use EL.

    .. sort of like [1] is analogous to HttpServletRequest.getSession( false ) and [2] is like HttpServletRequest.getSession( true ).
  • 9. Re: Sessions and Controllers best-practice in JSF2
    gimbal2 Guru
    Currently Being Moderated
    jmsjr wrote:
    EJP wrote:
    It's better because it ensures the bean gets instantiated, stuck in the session, which gets instantiated itself, the bean gets initialised, resource-injected, etc etc etc. Your way goes goes behind the scenes and hopes for the best, and raises complicated questions that don't really need answers.
    Thanks.

    1) But if I only want to check that the bean is in the session ... and I do NOT want to create an instance of the bean itself if it does not exist, then I presume I should still use ExternalApplication.getSessionMap.get(<beanName>).
    I can't think of a single reason why you would ever need to do that. Checking if a property of a bean in the session is populated however is far more reasonable to me.
  • 10. Re: Sessions and Controllers best-practice in JSF2
    jmsjr Newbie
    Currently Being Moderated
    gimbal2 wrote:
    jmsjr wrote:
    EJP wrote:
    It's better because it ensures the bean gets instantiated, stuck in the session, which gets instantiated itself, the bean gets initialised, resource-injected, etc etc etc. Your way goes goes behind the scenes and hopes for the best, and raises complicated questions that don't really need answers.
    Thanks.

    1) But if I only want to check that the bean is in the session ... and I do NOT want to create an instance of the bean itself if it does not exist, then I presume I should still use ExternalApplication.getSessionMap.get(<beanName>).
    I can't think of a single reason why you would ever need to do that. Checking if a property of a bean in the session is populated however is far more reasonable to me.
    In my case, there is an external application ( e.g. a workflow system from a vendor ) that will open a page in the JSF webapp.

    The user is already authenticated in the workflow system, and the external system from the vendor sends along the username and password and some parameters that define what the request is about ( e.g. whether to start a new case, or open an existing case ). There will be no login page in the JSF webapp as the authentication was already done externally by the workflow system.

    Basically, I was think of implementing a PhaseListener that would:

    1) Parse the request from the external system, and store the relevant username / password and other information into a bean which I store into the session.

    2) If the request parameter does not exist, then I go look for a bean in the session to see if the actual request came from within the JSF webapp itself ( e.g. if it was not triggered from the external workflow system ).

    3) If this bean does not exist at all ( e.g. It was triggered by something else other than the external workflow system that I was expecting ) then I would prefer that it would avoid all the JSF lifecycle for the current request and immediately do a redirect to a different page ( be it a static HTML, or another JSF page ).

    4) If the bean exist, then proceed with the normal JSF lifecycle.


    I could also, between [1] and [2], do a quick check to verify that the username and password is indeed valid on the external system ( they have a Java API to do that ), and if the credentials are not valid, I would also avoid all the JSF lifecycle for the current request and redirect to a different page.
  • 11. Re: Sessions and Controllers best-practice in JSF2
    EJP Guru
    Currently Being Moderated
    So you have some external authentication. I would try hard to express that aspect separately and not introduce dependencies on both that and the timing of session creation into the web-app.
  • 12. Re: Sessions and Controllers best-practice in JSF2
    r035198x Pro
    Currently Being Moderated
    Wouldn't form based security with JAAS ensure that the protected resource is served if the request includes j_username and j_password parameters?
    I would investigate that first option first.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points