aspose file tools*
The moose likes JSF and the fly likes Implicit navigation redirect causing new session Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of The Java EE 7 Tutorial Volume 1 or Volume 2 this week in the Java EE forum
or jQuery UI in Action in the JavaScript forum!
JavaRanch » Java Forums » Java » JSF
Bookmark "Implicit navigation redirect causing new session" Watch "Implicit navigation redirect causing new session" New topic
Author

Implicit navigation redirect causing new session

Brendan Healey
Ranch Hand

Joined: May 12, 2009
Posts: 218

Hi, I've got a strange thing happening with jsf 2.0 where I'm using "?faces-redirect=true" just to
try and get the URL in the browser pointing to the correct page but it's unexpectedly creating a
new session.

I've got page1.xhtml with the contents:



Then there's the backing bean:

backingBean.java



With or without "?faces-redirect=true" in the return string I navigate successfully to page2.xhtml.
The problem is that in my real world application I'm setting a property in the session scoped
bean which was is no longer set when page2 is rendered. Having verified that the property was
getting set as expected, I figured that for it to not be set subsequently it must have been cleared
OR page2 was using a different session to page1.

A bit of debugging shows that the backingBean constructor is firing AFTER the property is set but
only if faces-redirect=true is set in the return navigation string.

Could this be a bug or am I doing something silly?

Thanks for any help.
Brendan.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16019
    
  20

Well, first off, I feel obliged to recommend caution in using this new feature in JSF2. I saw a similar capability in Struts abused royally. There are some very useful things you can do with it, such as creating a "back" function that can return to one of a number of possible forwarding pages. But wholesale coding static views into an action processor unnecessarily hard-wires things into what was originally intended to be a more flexible framework. It also makes it harder for new people to follow the page flow, since, unlike the centralized faces-config file, there's no single place you can look to see how the views interconnect.

Regardless, I don't think a new session is being created. From what you said, you're initializing a bean before it's being constructed. That's a pretty good trick, and it implies that you're not doing what you think you're doing. It also confuses me, since I'm not sure if the bean you're referring to is the bean that contains the action processor or some other session object.

I can see where it might confuse the framework if you are navigating from within a bean instead of faces-config, but in this particular case what it sounds like is that you need to be injecting the affected bean into the bean that has the action in it so that the affected bean will have been constructed in advance. That's assuming I have any clue at all about what you're trying to do.

It also sounds like you need to read up on the JSF lifecycle (as defined for JSF 2), since you were determining the order of events by experimentation. A fundamental thing about JSF is that all the properties get validated, then set, then the action process fires, unless you explicitly short-circuit parts of this event sequence. So that much you should be able to count on.


Customer surveys are for companies who didn't pay proper attention to begin with.
Brendan Healey
Ranch Hand

Joined: May 12, 2009
Posts: 218
Tim Holloway wrote:Well, first off, I feel obliged to recommend caution in using this new feature in JSF2. I saw a similar capability in Struts abused royally. There are some very useful things you can do with it, such as creating a "back" function that can return to one of a number of possible forwarding pages. But wholesale coding static views into an action processor unnecessarily hard-wires things into what was originally intended to be a more flexible framework. It also makes it harder for new people to follow the page flow, since, unlike the centralized faces-config file, there's no single place you can look to see how the views interconnect.

Regardless, I don't think a new session is being created. From what you said, you're initializing a bean before it's being constructed. That's a pretty good trick, and it implies that you're not doing what you think you're doing. It also confuses me, since I'm not sure if the bean you're referring to is the bean that contains the action processor or some other session object.

I can see where it might confuse the framework if you are navigating from within a bean instead of faces-config, but in this particular case what it sounds like is that you need to be injecting the affected bean into the bean that has the action in it so that the affected bean will have been constructed in advance. That's assuming I have any clue at all about what you're trying to do.

It also sounds like you need to read up on the JSF lifecycle (as defined for JSF 2), since you were determining the order of events by experimentation. A fundamental thing about JSF is that all the properties get validated, then set, then the action process fires, unless you explicitly short-circuit parts of this event sequence. So that much you should be able to count on.


Perhaps it would be best if the URL shown in the browser window was correct, then I'd not need to consider this workaround. I appreciate that there are performance implications. The
key consideration is not confusing the users, the developers are paid to deal with these complications. This is a documented feature in JSF 2.0 and should work and it should be
legitimate to use it.

As far as I'm concerned there should be one session and one instance of a session scoped managed bean. I'm not creating anything, I'm not calling anything out of order, it's the container, not me. As I showed in the pseudo-code, there's one session bean, with a property and an action. The action is fired from an h:commandButton action="#{bean.action}". With implicit navigation the idea is that the method attached to h:commandButton action= is declared public String name() and it is then able to return a string which is the page that will be navigated to upon return from the method. If your in a page called /page1.xhtml and your action method has return "page2"; then the navigation handler will attempt to load page2.xhtml
without the need to reference rules in faces-config. It's a nice feature because it inlines the navigation without having to refer from java code to .xhtml web pages to web.xml files and
faces-config files etc... It's just a little bit simpler. Some people will like it, some won't, but best pass views onto the expert group.

I know the request processing lifecycle pretty well, but what have I done wrong? It works without ?faces-redirect=true, what have I done to call a method on a session bean before
it's been constructed, how could this be possible?

I strongly suspect that I've done nothing wrong and that there's a bug in the code.

Regards,
Brendan.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16019
    
  20

The redirect option also works in faces-config, so you don't need to resort to JSF2 for that. I use it to enforce container-managed security on my own apps.

However, it's architecturally impossible in Java, regardless of platform, framework, or toolkit to invoke any member method on an object before that object instance has been constructed. So I don't think that's what you're doing, here.

I do know what you're doing, but like I said, I saw that technique (mis)used in Struts to create a real navigational nightmare, so I'm mostly sticking to letting faces-config wire the navigation, except for cases like where a single view can be invoked from multiple predecessors and I want the OK and/or Cancel buttons to be able to return back to the view that invoked the new view. YMMV, of course. But "simpler" isn't always better. The scripting platforms such as PHP, RoR, and so forth are generally simpler, but they usually cost more to maintain for large-scale projects. If simple was the only criteria, I wouldn't waste my time on Enterprise Java.

JSF sessions are HTTP sessions, and there's exactly one and only one per web client/server combination. Or more accurately, at most only one, if no session has yet been created. Although JSF2 adds some new scoping options, the underlying HttpSession object is provided courtesy of J2EE. JSF session beans are merely JavaBeans bound to HttpSession attributes, and they can be, and often are accessible by non-JSF requests as well as JSF. The only real difference is that JSF can construct, initialize, and register them automatically as defined by faces-config.

There's only so much I can infer without actually seeing the project, which is why I mostly just suggest what I've found to be best practices. But do check to make sure that the offending object really is in session scope, because, as I said, the Java language architecture itself forbids what you seem to be encountering. My best guess would have to be that they're not really the same objects, either because the naming isn't quite identical (upper/lower case issues?) or that the scope is shorter than you think and the object is being created, set, discarded, and then re-created.
Brendan Healey
Ranch Hand

Joined: May 12, 2009
Posts: 218

What's happening is that in JSF 2.02-10 a backing bean declared as session scoped using
the @SessionScoped annotation (along with @ManagedBean) is treated as REQUEST SCOPED
and not session scoped. If the bean is declared in the faces-config file it works as expected.
Brendan Healey
Ranch Hand

Joined: May 12, 2009
Posts: 218
Brendan Healey wrote:
What's happening is that in JSF 2.02-10 a backing bean declared as session scoped using
the @SessionScoped annotation (along with @ManagedBean) is treated as REQUEST SCOPED
and not session scoped. If the bean is declared in the faces-config file it works as expected.


I need to hold my hands up here - I am guilty of not paying enough attention to the classes
that NetBeans was importing to resolve my @SessionScoped reference. With the correct class
imported everything is fine. Now I know! Thanks Tim for your comments along the way, it's
all helped me to resolve the problem.

 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Implicit navigation redirect causing new session