问题
I have been using JSF1.2 for login pages. If the user sits on the login page for too long (timeout situatation) and then tries to enter the id and password it fails with ViewExpired error (even though the id/password are correct). This all makes sense from JSF perspective to me. My solution has been to simply use Client for javax.faces.STATE_SAVING_METHOD. But that feels like a hack.
My app is migrating to JSF2.0. I would like my app to go back to server for STATE_SAVING_METHOD. But my requirement is that if the proper ID and password are submitted that app will accept it.
My other solution is to simply use servlets and not use JSF for login processing. But it seems like with all the ugprades to JSF2.0 that there might be something available now.
Any ideas would be greatly appreciated. Thank you.
回答1:
You could manually create and build the view when the restored view returns null
during postback. You can do this in a custom ViewHandler. Here's a kickoff example:
public class RestorableViewHandler extends ViewHandlerWrapper {
private ViewHandler wrapped;
public RestorableViewHandler(ViewHandler wrapped) {
this.wrapped = wrapped;
}
@Override
public UIViewRoot restoreView(FacesContext context, String viewId) {
UIViewRoot restoredView = wrapped.restoreView(context, viewId);
if (!(restoredView == null && context.isPostback())) {
return restoredView;
}
UIViewRoot createdView = createView(context, viewId);
context.setViewRoot(createdView);
try {
getViewDeclarationLanguage(context, viewId).buildView(context, createdView);
} catch (IOException e) {
throw new FacesException(e);
}
return createdView;
}
@Override
public ViewHandler getWrapped() {
return wrapped;
}
}
You may want to extend the if
check with a check if the viewId
represents the login page.
To get it to run, register it as follows in faces-config.xml
:
<application>
<view-handler>com.example.RestorableViewHandler</view-handler>
</application>
There are however technical limitations: the recreated view is exactly the same as it was during the initial request, so any modifications to the JSF component tree which are made thereafter, either by taghandlers or conditionally rendered components based on some view or even session scoped variables, are completely lost. In order to recreate exactly the desired view, you would need to make sure that those modifications are made based on request scoped variables (read: request parameters) instead of view or session scoped variables.
In other words, the state of the view should not depend on view or session scoped managed beans, but purely on request scoped managed beans.
Update: the OmniFaces JSF utility library has in the current 1.3 snapshot a reuseable solution in flavor of <o:enableRestorableView>
which can be embedded in <f:metadata>
. See also the <o:enableRestorableView> showcase page on snapshot site for a demo.
回答2:
Here are a couple of options that you could use:
Allow user to login after session times out JSF 2.0
(If you are open to using PrimeFaces they have a component you can use.) http://www.primefaces.org/showcase/ui/idlemonitorHome.jsf
回答3:
I have not tried it, but I think this is actually an ideal application for the new JSF feature "stateless views".
Just set "transient" on the JSF view:
<f:view transient="true">
...content...
</f:view>
A good explanation is here:
http://balusc.blogspot.de/2013/02/stateless-jsf.html
Also see this question: What is the usefulness of statelessness in JSF?
Unfortunately, this feature is only available in Mojarra V2.1 (and MyFaces 2.2) so you might need to upgrade from 2.0.
来源:https://stackoverflow.com/questions/12586413/can-you-post-to-jsf2-page-with-an-expired-session