This seems to work only when placed between the button (Mojarra 2.2, Glassfish 4). You will need these two <f:param tags javax.servlet.forward.request_uri and javax.servlet.forward.query_string to ensure you accurately redirect back to all types of URL (with or without query strings). Make sure you have something similar to the snippet below in your login page i.e. the page you specified in your web.xml for login
(<form-login-page>/login.xhtml</form-login-page>).
<h:commandButton value="Login" action="#{securityController.login()}">
<f:param name="redirect" value="#{requestScope['javax.servlet.forward.request_uri']}" />
<f:param name="query_string" value="#{requestScope['javax.servlet.forward.query_string']}" />
</h:commandButton>
You can then retrieve both parameters in the backing bean after form submission as below
public String login() {
try {
String nextPage = "/index.xhtml"; // have a default value in case the user goes to login page directly.
ExternalContext ctx = FacesContext.getCurrentInstance().getExternalContext();
Map<String, String> map = ctx.getRequestParameterMap();
String redirect = map.get("redirect");
String queryString = map.get("query_string");
HttpServletRequest request = (HttpServletRequest) ctx.getRequest();
request.login(this.username, this.password);
// here login is successful otherwise it would've thrown exception
// now let's check the kind of URL our user was going to
if (redirect != null && !redirect.isEmpty()) { // if redirect is null, return the default page
// please use faces-redirect = true to ensure URL change in the browser
if (queryString != null) {
nextPage = redirect + "?" + queryString + "&faces-redirect=true";
} else { // there is no query string, nextPage = redirect
nextPage = redirect + "&faces-redirect=true";
}
// Caveat: You may not need the next lines of code.
// I discovered that the `redirect` string has my context path
// value in it and so it was'nt redirecting. Remove the context path
if (nextPage.contains(request.getContextPath())) {
nextPage = nextPage.substring(request.getContextPath().length());
}
}
} catch (ServletException ex) {
Logger.getLogger(SecurityController.class.getName()).log(Level.SEVERE, null, ex);
// invalid username or password
return "/login.xhtml?failed=true"; // or login error page
}
return nextPage;
}
I hope this helps someone.