JSF Problems And Solutions

Retrieving values of HTML components
To retrieve the value of a HTML component adjust the following code:

FacesContext context = FacesContext.getCurrentInstance; UIViewRoot view = context.getViewRoot; HtmlInputText txtAnswer = (HtmlInputText)view.findComponent("testform:txtAnswer");

The parameter testform:txtAnswer indicates that the field txtAnswer is a child of the container testform.

Retrieving values of Managed Beans
Sometimes, you need to evaluate a value binding expression in your Java code. Use a sequence of statements such as the following:

FacesContext context = FacesContext.getCurrentInstance; ValueBinding binding = context.getApplication.createValueBinding("#{user.name}"); String name = (String) binding.getValue(context);

Including JSP pages

 * To include a JSP page with dynamic includes use  or  tags.
 * You must enclose the page in the 
 * You must provide an unique id for the subview
 * All template text and non-JSF tags inside included pages should be enclosed with the JSF  core tag.
 * If can load a Resource Bundle again in the included page.

Example

File: index.jsp <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>

  &lt;html&gt; My Title      &lt;/html&gt; 

File: navbuttons.jsp <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>



   <h:outputLabel for="txtExample"> <h:outputText id="helloInputLabel" value="#{msg.gotoexample}"/> </h:outputLabel> <h:inputText id="txtExample" styleClass="input1" > <f:validateLongRange minimum="1" maximum="#{exBean.maxpages}" /> </h:inputText> <h:message id="errors" for="txtExample" style="color: red"/> <f:verbatim> </f:verbatim> &lt;/f:subview&gt;

Advanced Navigation
To create an hyperlink to navigate to external pages programmaticaly you can use the code bellow: HtmlCommandLink comLink = new HtmlCommandLink; comLink.setOnmousedown("javascript:window.open('http://www.google.de','open_window');"); HtmlOutputText output = (HtmlOutputText)application.createComponent(HtmlOutputText.COMPONENT_TYPE); output.setValue("Open Google"); comLink.getChildren.add(output); or you can use the <h:commandLink> tag: <h:outputLink id="outID1" value="http://www.google.de" target="_blank"> <h:outputText id="outID2" value="Navigate to Google"/> </h:outputLink> To redirect a request to another page use the following code: <h:commandButton value="TESTING" type="submit" id="btntest" action="#{ebean.RedirectME}"></h:commandButton>

// Then create the code in your bean: public String RedirectME { FacesContext context = FacesContext.getCurrentInstance; ExternalContext ec = context.getExternalContext; try { ec.redirect("http://www.amazon.com"); }   catch (IOException ioe) { return "failure"; }   context.responseComplete; return "success"; }

Creating and Binding Action and ActionListener

 * To create dynamically a link to a defined outcome in the faces-config.xml, create a MethodBinding object and associate it to your component.
 * Don't use methods like addActionListener, they will probably not work, because the faces context will not get to restore the state of your listener class.

Example 1: Creating an ActionListener for your component.

MethodBinding mb = facesContext.getApplication .createMethodBinding("#{ebean.doIt}", new Class[] {ActionEvent.class}); HtmlCommandLink comLink = new HtmlCommandLink; comLink.setActionListener(mb);

// You have to define the following method in your bean: public void doIt(ActionEvent event) { ... }

Example 2: Creating an Action for your component.

MethodBinding mb = facesContext.getApplication .createMethodBinding("#{ebean.goToExample}", new Class[] {}); HtmlCommandLink comLink = new HtmlCommandLink; comLink.setAction(mb);

// You have to define the following method in your bean: public String goToExample { ... }

Example 3: Creating an Action for a method containing parameters. Solution using tags.

<h:commandLink action="#{UserViewPageBean.viewUser}" > <f:param name="UserID" value="#{user['UserID']}"/> <h:outputText value="#{user['UserID']}" /> </h:commandLink>

Example 4: Creating an Action for a method containing parameters. Solution using java code.

... // create a link HtmlCommandLink comLink = new HtmlCommandLink; comLink.setId("linkexample" + (count + 1)); comLink.setValue(bundle.getString("example") + " " + (count +1));

// add an Action MethodBinding mb = facesContext.getApplication .createMethodBinding("#{ebean.onExampleClick}", new Class[] {}); comLink.setAction(mb);

// add the parameter for the method onExampleClick UIParameter parameter = new UIParameter; parameter.setName("exampleID"); parameter.setValue(outcome); comLink.getChildren.add(parameter); ...

public String onExampleClick {	try { // get the faces context FacesContext facesContext = FacesContext.getCurrentInstance; Map map = facesContext.getExternalContext.getRequestParameterMap; for (Iterator iterator = map.entrySet.iterator; iterator.hasNext;) { Map.Entry entry = (Map.Entry) iterator.next; String key = (String)entry.getKey; String value = (String)entry.getValue; if (key.equals("exampleID")) {	   	 // update the current page page = Integer.parseInt(value); return "example" + value; }	 }	} catch (Exception e)	{ e.printStackTrace; }	return "mainmenu"; }

Example 5: Creating an Action using a constant value for the UIComponent.

... HtmlCommandLink comLink = new HtmlCommandLink; String outcome = "success"; setAction(comLink, outcome); ...

public static void setAction(UIComponent component, String attributeValue) { if (attributeValue == null) return; if (UIComponentTag.isValueReference(attributeValue)) setMethodBinding(component, "action", attributeValue,              new Class[] {}); else { FacesContext context = FacesContext.getCurrentInstance; Application app = context.getApplication; MethodBinding mb = new ConstantMethodBinding(attributeValue); component.getAttributes.put("action", mb); }  }   public static void setMethodBinding(UIComponent component, String attributeName,         String attributeValue, Class[] paramTypes) { if (attributeValue == null) return; if (UIComponentTag.isValueReference(attributeValue)) { FacesContext context = FacesContext.getCurrentInstance; Application app = context.getApplication; MethodBinding mb = app.createMethodBinding(attributeValue, paramTypes); component.getAttributes.put(attributeName, mb); }  } Note: The setAction and setMethodBinding methods should be in your final class defined. I think that other solution can be used for the problem of action using constant values. I did not test it, but the solution in the example 4 (described above) should work on it.

Preventing validations for the other components
To prevent validations for the other components in the form, we have one more thing to do: call the faces context method at the end of our value change listener, like this:

public void countryChanged(ValueChangeEvent event) { FacesContext context = FacesContext.getCurrentInstance; // change the language of the view object if(US.equals(event.getNewValue)) context.getViewRoot.setLocale(Locale.US); else context.getViewRoot.setLocale(Locale.CANADA);

context.renderResponse; } }

The call to skips the rest of the life cycle—including validation of the rest of the input components in the form—up to Render Response. Thus, the other validations are skipped and the response is rendered normally (in this case, the current page is redisplayed).

JavaScript And JSF
You’ll probably add client-side scripts to your JSF pages soon after you start using JSF. One common use is to submit a request when an input’s value is changed so that value change listeners are immediately notified of the change, like this:

<h:selectOneMenu onchange="submit"...>

Validating input at the client side
For example, you can add a command button and use JavaScript to validate the fields password and confirm password.

<h:commandButton type="button" onclick="checkPassword(this.form)"/>

...

function checkPassword(form) { var password = form["registerForm:password"].value; var passwordConfirm = form["registerForm:passwordConfirm"].value; if (password == passwordConfirm) form.submit; else alert("Password and password confirm fields don't match"); }

<h:commandLink actionListener="#{beanCategory.deleteAction}" onclick="if (!confirm('Would you really like to delete this record?')) return false"> <h:graphicImage value="/images/delete.gif" style="border: 0px" alt="#{translation.delete_tooltip}" /> </h:commandLink>

Using Filters for Authorization
Filters are a standard feature of the Servlet API—they allow you to perform additional processing on a request before and after it’s handled by traditional servlets (Intercepting Filter pattern [Alur, Crupi, Malks]).

Filters are commonly used for authorization duties because they can reroute a request if the user isn’t authorized to view the requested resource.


 * Redirects to the login page unauthenticated users and denies access to unauthorized resources. [JSF in Action, 2005, p. 546-551]

import java.io.IOException; import javax.servlet.*; import javax.servlet.http.*;

import org.jia.ptrack.domain.RoleType;

public class AuthorizationFilter implements Filter { FilterConfig config = null; ServletContext servletContext = null;

public AuthorizationFilter { }

public void init(FilterConfig filterConfig) throws ServletException {   config = filterConfig; servletContext = config.getServletContext; }

public void doFilter(ServletRequest request, ServletResponse response,                      FilterChain chain) throws IOException, ServletException {   Utils.log(servletContext, "Inside the filter");

HttpServletRequest httpRequest = (HttpServletRequest)request; HttpServletResponse httpResponse = (HttpServletResponse)response; HttpSession session = httpRequest.getSession;

String requestPath = httpRequest.getPathInfo; Visit visit = (Visit)session.getAttribute(Constants.VISIT_KEY); if (visit == null) {     session.setAttribute(Constants.ORIGINAL_VIEW_KEY, httpRequest.getPathInfo); Utils.log(servletContext, "redirecting to " + httpRequest.getContextPath +               Constants.LOGIN_VIEW); httpResponse.sendRedirect(httpRequest.getContextPath +                               Constants.LOGIN_VIEW); }   else {     session.removeAttribute(Constants.ORIGINAL_VIEW_KEY); RoleType role = visit.getUser.getRole;

if ((role.equals(RoleType.UPPER_MANAGER) && requestPath.indexOf(Constants.PROTECTED_DIR) > 0) ||         (!role.equals(RoleType.PROJECT_MANAGER) && requestPath.indexOf(Constants.EDIT_DIR) > 0)) {       String text = Utils.getDisplayString(Constants.BUNDLE_BASENAME,                                             "PathNotFound",                                             new Object[] { requestPath },                                             request.getLocale); httpResponse.sendError(HttpServletResponse.SC_NOT_FOUND,                              text); }     else {       chain.doFilter(request, response); }   }    Utils.log(servletContext, "Exiting the filter"); }

public void destroy { } }

Problems with Cookies
Problem: If you are using more than 20 cookies or the cookie size is bigger than 4Kb, please see this problem http://www.thismuchiknow.co.uk/?p=13

Solution: Try to put everything in one String separated by "@@" as separator. The order of the objects to save and load is important. It will reduce that amount of cookies.