Tuesday, February 12, 2013

Stateless JSF

Just wanted to spread the word: as per Mojarra 2.1.19 / 2.2.0 (both currently only available as snapshot) it's very easy to make the JSF view completely stateless by just setting the transient attribute of the <f:view> to true:


    <f:view transient="true">
        Your regular content
    </f:view>

That's all. Really. It works for me. The view state isn't been created and thus the session also won't be created when not created yet. This is very useful for e.g. a JSF based login form on the public/stateless side of a website.

Remember to put the associated managed bean in the request scope instead of view/session scope, otherwise you're simply defeating the meaning of the word "stateless".

A lot of people have been waiting very long for this. See also issue 2731 and this blog of Mojarra developer Manfred Riem.

16 comments:

Unknown said...

I don't think I get it. Isn't @RequestScoped already "stateless"? How is that different?

BalusC said...

It concerns the JSF view state (the JSF component tree state). It's by default stored in the session scope and identified by javax.faces.ViewState hidden input field.

Richard said...

BalusC,

Love your work!

I haven't used the f:view tag for many years since moving to Facelets. Is there a way to do this without re-introducing it?

If not, where should f:view be placed in order to ensure it preempts any stateful initialization?

Regards,

Richard.

DWuysan said...

Will it work when using f:ajax?

BalusC said...

@Richard: just in master template. Assuming that you've XML namespace declarations in <html> tag, then you can put the <f:view> as immediate child, around the <h:head> and <h:body>.

@DWuysan: yes, <f:ajax will keep working, but you can't use a view scoped bean, it would be recreated on every request. You'd need to fiddle with request parameters to maintain state.

gabriel! said...

BalusC you're the man! Thanks so much for this update! Very appreciated. I have two questions for you, firstly, what do you mean we shouldn't use SessionScoped? I thought that was stored in the http session map? How does this affect those beans? Unless you only meant that it would defeat the purpose of stateless jsf.
2nd questions, does this in any way require a change in the way we think about Ajax or partial state validation? Must we take new things into account?
Thanks man!

Thang Pham said...

Hi BalusC. Can you explain a bit on how ajax request would work with stateless mode. So take a case of two selectOneMenu, where the selection of one change the values of the other. In stateful JSF, we have scoped, then upon selection of one selectOneMenu, we update the list of the second selectOneMenu in the backend, then re-render the second list. How do we do that now with JSF stateless, BalusC? pure jQuery?

Liyu Wang said...

It seems that feature broken with AJAX Post redirect, or with RichFaces4.2, If I call with stateless enabled. it called the function, but the rendered result is empty, for example:

BalusC said...

@Liyu: it will obviously break where state is required, such as in ajax postbacks which involve conditional renders.

httPants said...

Does the jsf stateless view feature make the omni faces enableRestorableView tag obsolete?

palkonyves said...

Hey,
I (using mojarra 2.1.2) realized the view tree is recreated every time even if I have a session.
Am I right that performance issue does not only come from the fact the view state is stored for forms, but also from the time cost of rebuilding the view tree on every request?

I don't understand that if view state is stored for every session, why does the view tree need to be rebuilt on every request, why cannot it be pooled and get it's state reset before use?

It seems to me that the only benefit of it is the ability to programmatically add components to the view tree on request.

Thanks in advance,
Pal

Unknown said...

I did as you mentioned,using transient attribute in view tag, but still in source code, I see
<input type="hidden" name="javax.faces.ViewState" .....

BalusC said...

@Gita: check the input value, not the name.

Unknown said...

Sorry I had not looked at the whole input tag.
input type="hidden" name="javax.faces.ViewState" id="j_id1:javax.faces.ViewState:0" value="stateless" autocomplete="off" /
As you see the value is "stateless"

Unknown said...

Thank you. You are wonderful. I am new in JSF and I am going to use it with primefaces in a new project. To be honest with you, I am little bit worried about that since no one in our company use JSF and I suggested to develope this project with JSF & Primefaces. Do you think I am in right path? I try my best to read all your articles. Thank you again.

Unknown said...

BalusC,

Is it possible to use this approach for pages containing multiple forms and make only some of these forms stateless, while other forms stay statefull.

I tried to make a simple example with 2 forms, and wrap one form in . However, both forms became stateless.