Passing the locale value in URL - jsf

I have a requirement where I need to display the same page in different language when the user selects a language from the dropdown.
For this I am using a selectOneMenu with multiple languages. When the user selects a language(locale) , the value should be appended to the url.
I have used the below code but it replaces the already present parameters from the url with locale.
Is there any way I can append the locale parameter without disturbing the parameters already present.
FacesContext ctx = FacesContext.getCurrentInstance();
String contxRoot = ctx.getExternalContext().getRequestContextPath();
String viewId = ctx.getViewRoot().getViewId();
String URL=viewId+"?language="+this.selectedLaguage;
try {
FacesContext.getCurrentInstance().getExternalContext().redirect(contxRoot+URL);
} catch (IOException e) {
e.printStackTrace();
}
Any help would be appreciated.

This code is not a beauty, but you could try
FacesContext ctx = FacesContext.getCurrentInstance();
String contxRoot = ctx.getExternalContext().getRequestContextPath();
String initialUri = ((HttpServletRequest) ctx.getExternalContext().getRequest()).getRequestURI();
String languageParameter = "?language="+this.selectedLaguage;
try {
FacesContext.getCurrentInstance().getExternalContext().redirect(contxRoot+initialUri+languageParameter);
} catch (IOException e) {
e.printStackTrace();
}

This sounds like a good candidate for storing in a #SessionScoped bean. Set the language in the bean and it can be used by all pages requested by the user (during the course of this session, of course).
A custom filter that intercepts a request and sets the language from the url and redirects appropriately can be option if, for example, a user wants to link to a URL in a particular language. Whether or not you actually want to allow that is up to you...

Related

How to reuse the old views in JSF

I have concurrent view limit exceeded problem in icefaces. It supports not more than 50 views per one session. In the process of finding issue with the code, I have doubt regarding view reusability.
Consider the below cases.
Case 1:
Returning empty string would recreate a view though the user stays on the current page, as shown below.
public String submit(){
//...
return "";
}
Case 2:
But, below code would reuse the old view.
public String submit(){
//...
return null;
}
Case 3:
I think, below code snippet would also do the same. Correct me here, if I am wrong.
public String submit() {
// ...
return "viewId?faces-redirect=true";
}
What is the difference between case 2 and case 3?
UPDATE:
I have tested an application with JSF 1.2, it allows all the 3 cases, as mentioned above.
In my bean I am using the following code
public String saveData() {
//String returnString = "";//Case 1 : works - user stays on the same page
//String returnString = null;//Case 2: works - user stays on the same page
// Case 3:
String viewId = FacesContext.getCurrentInstance().getViewRoot().getViewId();
System.out.println("view id = "+ viewId);
String returnString = viewId+"?faces-redirect=true";
System.out.println("return string = "+ returnString);
return returnString;
}
I have deployed the above application in jetty.In the above example, every time the method saveData() is called, the user stays on the same page with his filled in data in input fields, I infer from this that, its reusing the old page or view(I am not clear with a view in JSF). This is happening in all the 3 cases, so not sure of the exact difference, How to experience this difference? What is a view from JSF perspective?

ExternalContext#dispatch() doesn't work

I have server-side coundown counter. When it == 0, method should execute ExternalContext#dispatch(), but it didn't do it. Method ExternalContext#redirect() works correctly on this place.
....
}else{
try {
FacesContext.getCurrentInstance().getExternalContext().dispatch("result.xhtml");
} catch (IOException e) {
e.printStackTrace();
}
}
....
I tried a few ways of the spelling url(result,result.xhtml,\result.xhtml etc.) with the same result.
This is not the right way to let JSF navigate to a different view.
If you're inside an action method, you should be returning it as string instead.
public String submit() {
// ...
return "result.xhtml";
}
Or if you're not inside an action method and couldn't change it to a fullworthy action method for some unclear reason, then use NavigationHandler#handleNavigation() instead.
FacesContext context = FacesContext.getCurrentInstance();
context.getApplication().getNavigationHandler().handleNavigation(context, null, "result.xhtml");

JSF navigating to a different view programatically

My application has a save and retrieve function. I have the save/retrieve working in that the objects are saved to a database and retrieved correctly. However, in my retrieve landing page, depending on the state of the saved application, I either want to validate some details with the user, or silently navigate to the last accessed view. The latter is where I'm having trouble.
We're using spring beans and in my SaveAndRetrieve page bean I have:
#PostConstruct
public void initialise() {
caseNotFound = false;
caseReference = saveAndRetrieveActionHandler.getRequestedCaseReference();
LOGGER.debug("Retrieve initialise. Case ref is {}", caseReference);
if (caseReference != null) {
try {
saveAndRetrieveActionHandler.retrieveApplicationByCaseRef();
LOGGER.debug("Retrieve initialise - case found");
final NavigationOutcome outcome = saveAndRetrieveActionHandler.getLastAccessedView();
if (outcome.getApplicationState() == ApplicationState.QUOTE) {
LOGGER.info("Quote retrieved, navigating to view");
// HERE IS WHERE THE TROUBLE LIES! THIS DOESNT WORK
FacesUtils.setNextViewNavigation(outcome.getViewId());
}
} catch (final FrameworkException fe) {
LOGGER.debug("Exception caught {}", fe);
caseNotFound = true;
}
}
}
outcome is an enumeration containing amongst other things the view I need to navigate to, and the application state (another enumeration). If applicationState is quote, I want to silently navigate. For all other applicationStates I want to challenge the user to verify them.
My facesUtils method is:
public static void setNextViewNavigation(final String p_lastAccessedViewId) {
if (p_lastAccessedViewId != null) {
getCurrentViewRoot().setViewId(p_lastAccessedViewId);
}
}
I've also tried calling this method
public static void navigateToOutcome(final String p_outcome) {
final FacesContext context = getFacesContext();
final NavigationHandler navigationHandler = context.getApplication().getNavigationHandler();
navigationHandler.handleNavigation(context, null, p_outcome);
}
Despite my efforts, I'm seeing the landing page wheras I want to silently navigate to the saved page
Basically I want to abort the current lifecycle and reset the viewroot to the saved view. (note I am not saving the component tree itself, just my business objects)
One more piece of information, this is jsf1.2, but with facelets. I cannot use any jsf2 specific functionality, nor can I use any third party JSF extenstions.
Help please!
We solved this by using a ui:include tag with the src attribute being a jsf method that determines the name of the page to navigate to.

request.getSession() is null

I will appreciate if someone help me with the following problem.
I have a jasper report which i fill in a PrintingBean and its all good. The moment I clicked on a print preview button (opening the applet) my app throws a null pointer exception at:
if (bean.getPrintingDataList() != null && !bean.getPrintingDataList().isEmpty())
It seems like it makes new session (but I can't see that on gui, its all good). My manageBean is a SessionScoped. This is my whole method:
private void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
JasperPrint jasperPrint = null;
try {
PrintingBean bean = (PrintingBean) request.getSession().getAttribute("printMB");
if (bean.getPrintingDataList() != null && !bean.getPrintingDataList().isEmpty()) {
jasperPrint = printManager.print(bean.getPrintingDataList());
}
} catch (Exception ex) {
Logger.getLogger(JasperPrintServlet.class.getName()).log(Level.SEVERE, null, ex);
}
if (jasperPrint != null) {
response.setContentType("application/octet-stream");
ServletOutputStream ouputStream = response.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(ouputStream);
oos.writeObject(jasperPrint);
oos.flush();
oos.close();
ouputStream.flush();
ouputStream.close();
}
}
The session is maintained by a cookie with the name JSESSIONID. Normally, this cookie is set by the server on start of session and this cookie is returned back from client to server on every subsequent single HTTP request throughout the session. The client (the webbrowser) does this all transparently. See also How do servlets work? Instantiation, sessions, shared variables and multithreading.
In the applet you need to simulate the same as the webbrowser is doing. When the applet connects to the servlet and needs to access the same session as the page which is serving the applet, then you should make sure that you append the very same session cookie to the HTTP request which is been sent by the applet.
The easiest is to pass the session ID as a parameter to the applet:
<param name="JSESSIONID" value="#{session.id}">
(note: I'm assuming that you're using Facelets as view technology, if you were using JSP, then you should use ${pageContext.session.id} instead)
So that you can set the needed session cookie in the applet accordingly:
String jSessionID = getParameter("JSESSIONID");
URL servletURL = new URL(getCodeBase(), "yourServletURL");
URLConnection connection = servletURL.openConnection();
connection.setRequestProperty("Cookie", "JSESSIONID=" + jSessionID);
// ...
This should give you the same session back in the servlet on request.getSession().
If there is a request than there must be a session. I think .getAttribute("printMB") is null. You must check before cast it to PrintingBean.

Programmatically control login with Servlet 3.0

I've tested the default security containers in Glassfish 3.0.1 and come to the conclusion that I won't spend any more time on that. Instead I want to control the verification myself. But I need some guidance to get me on right track.
At the moment I have a UserBean that has a login/logout function (see below). And I don't want to use the *j_security_check* built in container, but use core JSF 2.0.
My questions are;
Do I need a ServletFilter to redirect traffic if the user is not logged in (if accessing certain folders)?
How do I store User Pricipals after the user successfully logged in ?
Appreciate any help or link to a example, greetings Chris.
PS. Excuse me for clustering two questions together
#ManagedBean
#SessionScoped
public class UserBean {
private AuthenticateUser authenticateUser;
...
public String login() {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
JsfUtil.log("Username : " +authenticateUser.getUserName());
JsfUtil.log("Password : " +authenticateUser.getPassword());
AuthenticateUser authRequest = authenticationFacade.find(authenticateUser);
try {
if(!authRequest.equals(authenticateUser))
return "/loginError";
request.login(authenticateUser.getUserName(), authenticateUser.getPassword());
return "";
} catch(ServletException e){
JsfUtil.addErrorMessage(e, "Incorrect username or password, please try again.");
return "/loginError";
}
...
public String logOut() {
String result = "/index?faces-redirect=true";
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
try {
request.logout();
} catch (ServletException e) {
JsfUtil.log("Failed to logout user!" +e.getRootCause().toString());
result = "/loginError?faces-redirect=true";
}
return result;
}
When you want to utilize request.login(), then you should really have configured a Realm in the container which represents the user database. But you seem to have replaced the Realm by some AuthenticationFacade. In this case, the request.login() is not useful for you.
You need to just put the user in the session scope and intercept on that. Here's a kickoff example:
#ManagedBean
#SessionScoped
public class UserManager {
#EJB
private UserService userService;
private String username;
private String password;
private User current;
public String login() {
current = userService.find(username, password);
if (current == null) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Unknown login, try again"));
return null;
} else {
return "userhome?faces-redirect=true";
}
}
public String logout() {
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "index?faces-redirect=true";
}
public boolean isLoggedIn() {
return current != null;
}
// Getters/setters (but do NOT provide a setter for current!)
}
When taking authentication in hands like this, then you definitely need a filter to restrict access. When using container managed security you would typically specify it as <url-pattern> of <security-constraint> for this. But without it, you've to take it in your hands. It's good to know that JSF managed beans are keyed by their managed bean name in any scope.
UserManager userManager = ((HttpServletRequest) request).getSession().getAttribute("userManager");
if (userManager == null || !userManager.isLoggedIn()) {
((HttpServletResponse) response).sendRedirect("login.xhtml");
} else {
chain.doFilter(request, response);
}
Map the above filter on the desired URL-pattern.
When you still want to reconsider using container managed authentication, then the following related answers may be useful:
Java EE Login Page Problem (and Configuring Realm in Glassfish)
Performing user authentication in Java EE / JSF using j_security_check
Be aware if you are if you are using JDBC realm security. There are some fixed/expected words in the fields where you configure the realm in the Glassfish admin console.
In the JAAS Context: filed, you have to type: jdbcRealm. This keyword makes the security container use the expected JDBC realm. If you type something else, it won't work.
Here is good example, done by Gordan Jugo; Netbeans/Glassfish JDBC Security Realm

Resources