Author: mrdon Date: Fri Jun 16 22:51:12 2006 New Revision: 414999 URL: http://svn.apache.org/viewvc?rev=414999&view=rev Log: Made JSF interceptors able to be included in non-jsf actions/apps; improved JSF example in showcase to allow adding of employees, better page layout, match other similar examples, add simple validation, add jsf example link to main page
WW-1320 - Added: struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EditEmployeeAction.java - copied, changed from r413546, struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeAction.java struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/ListEmployeesAction.java - copied, changed from r413546, struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/IndexAction.java struts/action2/trunk/apps/showcase/src/main/webapp/jsf/editEmployee.jsp - copied, changed from r413546, struts/action2/trunk/apps/showcase/src/main/webapp/jsf/employee.jsp struts/action2/trunk/apps/showcase/src/main/webapp/jsf/listEmployees.jsp Removed: struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeAction.java struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/IndexAction.java struts/action2/trunk/apps/showcase/src/main/webapp/jsf/employee.jsp struts/action2/trunk/apps/showcase/src/main/webapp/jsf/index.jsp Modified: struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/action/EmployeeAction.java struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeDao.java struts/action2/trunk/apps/showcase/src/main/resources/xwork-jsf.xml struts/action2/trunk/apps/showcase/src/main/webapp/showcase.jsp struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesInterceptor.java struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesSetupInterceptor.java Modified: struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/action/EmployeeAction.java URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/action/EmployeeAction.java?rev=414999&r1=414998&r2=414999&view=diff ============================================================================== --- struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/action/EmployeeAction.java (original) +++ struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/action/EmployeeAction.java Fri Jun 16 22:51:12 2006 @@ -31,7 +31,7 @@ import java.util.List; /** - * EmployeeAction. + * EditEmployeeAction. */ public class EmployeeAction extends AbstractCRUDAction implements Preparable { @@ -83,7 +83,7 @@ public void setEmployeeDao(EmployeeDao employeeDao) { if (log.isDebugEnabled()) { - log.debug("EmployeeAction - [setEmployeeDao]: employeeDao injected."); + log.debug("EditEmployeeAction - [setEmployeeDao]: employeeDao injected."); } this.employeeDao = employeeDao; } Copied: struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EditEmployeeAction.java (from r413546, struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeAction.java) URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EditEmployeeAction.java?p2=struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EditEmployeeAction.java&p1=struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeAction.java&r1=413546&r2=414999&rev=414999&view=diff ============================================================================== --- struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeAction.java (original) +++ struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EditEmployeeAction.java Fri Jun 16 22:51:12 2006 @@ -21,38 +21,40 @@ import com.opensymphony.xwork.ActionSupport; -public class EmployeeAction extends ActionSupport { - - private static final long serialVersionUID = 1L; - - private Employee employee; - private int id; - - public EmployeeAction() { - employee = new Employee(); - } - - public Employee getEmployee() { - return employee; - } - - public String[] getAllSkills() { - return EmployeeDao.getSkills(); - } - - public void setId(int id) { - this.id = id; - } - +public class EditEmployeeAction extends ActionSupport { + + private static final long serialVersionUID = 1L; + + private Employee employee; + + private int id; + + public EditEmployeeAction() { + employee = new Employee(); + } + + public Employee getEmployee() { + return employee; + } + + public String[] getAllSkills() { + return EmployeeDao.getSkills(); + } + + public void setId(int id) { + this.id = id; + } + public String execute() { - this.employee = EmployeeDao.getEmployee(id); - return SUCCESS; + if (id > 0) { + this.employee = EmployeeDao.getEmployee(id); + } + return SUCCESS; } - + public String save() { - EmployeeDao.save(employee); - return "index"; + EmployeeDao.save(employee); + return "index"; } - -} +} Modified: struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeDao.java URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeDao.java?rev=414999&r1=414998&r2=414999&view=diff ============================================================================== --- struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeDao.java (original) +++ struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeDao.java Fri Jun 16 22:51:12 2006 @@ -2,24 +2,29 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.TreeMap; public class EmployeeDao { private static String[] skills; - private static List<Employee> employees; - + private static Map<Integer,Employee> employees; + + private static int counter = 4; + static { - employees = new ArrayList<Employee>(); - employees.add(new Employee(0, "Tom Jones", new String[]{"Java", "PHP"})); - employees.add(new Employee(1, "Bart Simpson", new String[]{"PHP"})); - employees.add(new Employee(2, "Sofia Jones", new String[]{"Java"})); + employees = new TreeMap<Integer,Employee>(); + employees.put(1, new Employee(1, "Tom Jones", new String[]{"Java", "PHP"})); + employees.put(2, new Employee(2, "Bart Simpson", new String[]{"PHP"})); + employees.put(3, new Employee(3, "Sofia Jones", new String[]{"Java"})); skills = new String[]{"Java", "PHP", "C#"}; } - public static List<Employee> getEmployees() { + public static Map<Integer,Employee> getEmployees() { return employees; } @@ -28,7 +33,13 @@ } public static void save(Employee e) { - employees.set(e.getId(), e); + if (e.getId() > 0) { + employees.put(e.getId(), e); + } else { + e.setId(counter); + employees.put(counter, e); + counter++; + } } public static String[] getSkills() { Copied: struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/ListEmployeesAction.java (from r413546, struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/IndexAction.java) URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/ListEmployeesAction.java?p2=struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/ListEmployeesAction.java&p1=struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/IndexAction.java&r1=413546&r2=414999&rev=414999&view=diff ============================================================================== --- struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/IndexAction.java (original) +++ struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/ListEmployeesAction.java Fri Jun 16 22:51:12 2006 @@ -17,27 +17,29 @@ */ package org.apache.struts.action2.showcase.jsf; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import java.util.Map; +import java.util.Set; import com.opensymphony.xwork.ActionSupport; -public class IndexAction extends ActionSupport { - - private static final long serialVersionUID = 1L; - - private List loadedEmployees; - - public List getEmployees() { - System.out.println("getting employees:"+loadedEmployees); - return loadedEmployees; - } +public class ListEmployeesAction extends ActionSupport { + + private static final long serialVersionUID = 1L; + + private Map loadedEmployees; + + public Collection<Employee> getEmployees() { + // Why can't JSF handle the collection itself?? + return new ArrayList<Employee>(loadedEmployees.values()); + } public String execute() { - System.out.println("executing"); - loadedEmployees = EmployeeDao.getEmployees(); - - return SUCCESS; + loadedEmployees = EmployeeDao.getEmployees(); + + return SUCCESS; } - -} +} Modified: struts/action2/trunk/apps/showcase/src/main/resources/xwork-jsf.xml URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/src/main/resources/xwork-jsf.xml?rev=414999&r1=414998&r2=414999&view=diff ============================================================================== --- struts/action2/trunk/apps/showcase/src/main/resources/xwork-jsf.xml (original) +++ struts/action2/trunk/apps/showcase/src/main/resources/xwork-jsf.xml Fri Jun 16 22:51:12 2006 @@ -5,16 +5,16 @@ <package name="jsf" extends="struts-default, struts-jsf" namespace="/jsf"> - <action name="index" class="org.apache.struts.action2.showcase.jsf.IndexAction"> + <action name="listEmployees" class="org.apache.struts.action2.showcase.jsf.ListEmployeesAction"> <interceptor-ref name="jsfStack"/> <result name="success" type="jsf" /> </action> - <action name="employee" class="org.apache.struts.action2.showcase.jsf.EmployeeAction"> + <action name="editEmployee" class="org.apache.struts.action2.showcase.jsf.EditEmployeeAction"> <interceptor-ref name="basicStack"/> <interceptor-ref name="jsfStack"/> <result name="success" type="jsf" /> - <result name="index" type="redirect-action">index</result> + <result name="index" type="redirect-action">listEmployees</result> </action> </package> Copied: struts/action2/trunk/apps/showcase/src/main/webapp/jsf/editEmployee.jsp (from r413546, struts/action2/trunk/apps/showcase/src/main/webapp/jsf/employee.jsp) URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/src/main/webapp/jsf/editEmployee.jsp?p2=struts/action2/trunk/apps/showcase/src/main/webapp/jsf/editEmployee.jsp&p1=struts/action2/trunk/apps/showcase/src/main/webapp/jsf/employee.jsp&r1=413546&r2=414999&rev=414999&view=diff ============================================================================== --- struts/action2/trunk/apps/showcase/src/main/webapp/jsf/employee.jsp (original) +++ struts/action2/trunk/apps/showcase/src/main/webapp/jsf/editEmployee.jsp Fri Jun 16 22:51:12 2006 @@ -31,26 +31,28 @@ <body> - <h2>Modify Employee</h2> + <h1>Modify Employee</h1> <h:form> <h:inputHidden value="#{action.employee.id}" /> - <h:panelGrid columns="2"> - <h:outputText value="ID:" /> - <h:outputText value="#{action.employee.id}" /> + <h:panelGrid columns="3"> <h:outputText value="Name:" /> - <h:inputText size="30" value="#{action.employee.name}" /> + <h:inputText id="name" size="30" value="#{action.employee.name}" required="true"> + <f:validateLength maximum="30" minimum="2" /> + </h:inputText> + <h:message for="name" /> <h:outputText value="Skills:" /> - <h:selectManyCheckbox value="#{action.employee.skills}"> + <h:selectManyCheckbox id="skills" value="#{action.employee.skills}"> <f:selectItem itemValue="Java" itemLabel="Java" /> <f:selectItem itemValue="PHP" itemLabel="PHP" /> <f:selectItem itemValue="Ruby" itemLabel="Ruby" /> - </h:selectManyCheckbox> + </h:selectManyCheckbox> + <h:message for="skills" /> </h:panelGrid> <h:commandButton value="Submit" action="#{action.save}" /> <br /><br /> - <h:outputLink value="index.action"> + <h:outputLink value="listEmployees.action"> <h:outputText value="Back" /> </h:outputLink> </h:form> Added: struts/action2/trunk/apps/showcase/src/main/webapp/jsf/listEmployees.jsp URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/src/main/webapp/jsf/listEmployees.jsp?rev=414999&view=auto ============================================================================== --- struts/action2/trunk/apps/showcase/src/main/webapp/jsf/listEmployees.jsp (added) +++ struts/action2/trunk/apps/showcase/src/main/webapp/jsf/listEmployees.jsp Fri Jun 16 22:51:12 2006 @@ -0,0 +1,66 @@ +<%-- + + Copyright 2006 The Apache Software Foundation. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + $Id: welcome.jsp 371852 2006-01-24 07:25:10Z craigmcc $ + +--%> + +<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %> +<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %> + +<f:view> + +<html> + + <head> + <title>JSF Integration Examples</title> + </head> + + <body> + <h1>Employee List</h1> + + <h:dataTable value="#{action.employees}" var="e"> + <h:column> + <f:facet name="header"> + <h:outputText value="ID" />${e} } + </f:facet> + <h:outputLink value="editEmployee.action"> + <f:param name="id" value="#{e.id}" /> + <h:outputText value="#{e.id}" /> + </h:outputLink> + </h:column> + <h:column> + <f:facet name="header"> + <h:outputText value="Name" /> + </f:facet> + <h:outputText value="#{e.name}" /> + </h:column> + <h:column> + <f:facet name="header"> + <h:outputText value="Skills" /> + </f:facet> + <h:outputText value="#{e.skills}" /> + </h:column> + </h:dataTable> + + <h:outputLink value="index.jsp"> + <h:outputText value="Back" /> + </h:outputLink> + </body> + +</html> + +</f:view> Modified: struts/action2/trunk/apps/showcase/src/main/webapp/showcase.jsp URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/src/main/webapp/showcase.jsp?rev=414999&r1=414998&r2=414999&view=diff ============================================================================== --- struts/action2/trunk/apps/showcase/src/main/webapp/showcase.jsp (original) +++ struts/action2/trunk/apps/showcase/src/main/webapp/showcase.jsp Fri Jun 16 22:51:12 2006 @@ -62,6 +62,9 @@ <!-- freemarker --> <li><saf:url id="url" value="/freemarker" /><saf:a href="%{#url}">Freemarker Example</saf:a></li> + + <!-- JavaServer Faces --> + <li><saf:url id="url" value="/jsf" /><saf:a href="%{#url}">JavaServer Faces Example</saf:a></li> </ul> </p> Modified: struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesInterceptor.java URL: http://svn.apache.org/viewvc/struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesInterceptor.java?rev=414999&r1=414998&r2=414999&view=diff ============================================================================== --- struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesInterceptor.java (original) +++ struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesInterceptor.java Fri Jun 16 22:51:12 2006 @@ -19,7 +19,12 @@ import javax.faces.context.FacesContext; +import com.opensymphony.xwork.Action; +import com.opensymphony.xwork.ActionContext; import com.opensymphony.xwork.ActionInvocation; +import com.opensymphony.xwork.Result; +import com.opensymphony.xwork.config.entities.ActionConfig; +import com.opensymphony.xwork.config.entities.ResultConfig; import com.opensymphony.xwork.interceptor.Interceptor; /** @@ -28,63 +33,84 @@ */ public class FacesInterceptor extends FacesSupport implements Interceptor { - private static final long serialVersionUID = -5418255964277566516L; + private static final long serialVersionUID = -5418255964277566516L; - /** - * Not used - */ - public void init() { - } - - /** - * Adapts the phase workflow to Action 2 - * - * @param invocation - * The action invocation - * @return The string result code - */ - public String intercept(ActionInvocation invocation) throws Exception { - - FacesContext context = FacesContext.getCurrentInstance(); - - if (context.getRenderResponse()) { - return invocation.invoke(); - } else { - String viewId = invocation.getProxy().getNamespace() + '/' - + invocation.getProxy().getActionName(); - executePhase(viewId, context); - - if (context.getResponseComplete()) { - // Abort the chain as the result is done - return null; - } else { - if (invocation.getResultCode() != null) { - return invocation.getResultCode(); - } else { - return invocation.invoke(); - } - } - } - } - - /** - * Executes the specific phase. The phase id is constructed as a composite - * of the namespace and action name. - * - * @param viewId - * The view id - * @param facesContext - * The current faces context - * @return True if the next phases should be skipped - */ - protected boolean executePhase(String viewId, FacesContext facesContext) { - return false; - } - - /** - * Not used - */ - public void destroy() { - } + /** + * Marker key for the ActionContext to dictate whether to treat the request + * as a JSF faces request and therefore process the Faces phases + */ + protected static final String FACES_ENABLED = "facesEnabled"; + + /** + * Not used + */ + public void init() { + } + + /** + * Adapts the phase workflow to Action 2 + * + * @param invocation + * The action invocation + * @return The string result code + */ + public String intercept(ActionInvocation invocation) throws Exception { + + if (isFacesEnabled(invocation.getInvocationContext())) { + FacesContext context = FacesContext.getCurrentInstance(); + + if (context.getRenderResponse()) { + return invocation.invoke(); + } else { + + String viewId = invocation.getProxy().getNamespace() + '/' + + invocation.getProxy().getActionName(); + executePhase(viewId, context); + + if (context.getResponseComplete()) { + // Abort the chain as the result is done + return null; + } else { + if (invocation.getResultCode() != null) { + return invocation.getResultCode(); + } else { + return invocation.invoke(); + } + } + } + } else { + return invocation.invoke(); + } + } + + /** + * Executes the specific phase. The phase id is constructed as a composite + * of the namespace and action name. + * + * @param viewId + * The view id + * @param facesContext + * The current faces context + * @return True if the next phases should be skipped + */ + protected boolean executePhase(String viewId, FacesContext facesContext) { + return false; + } + + /** + * Not used + */ + public void destroy() { + } + + /** + * Determines whether to process this request with the JSF phases + * + * @param ctx The current action context + * @return True if it is a faces-enabled request + */ + protected boolean isFacesEnabled(ActionContext ctx) { + return ctx.get(FACES_ENABLED) != null; + } } Modified: struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesSetupInterceptor.java URL: http://svn.apache.org/viewvc/struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesSetupInterceptor.java?rev=414999&r1=414998&r2=414999&view=diff ============================================================================== --- struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesSetupInterceptor.java (original) +++ struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesSetupInterceptor.java Fri Jun 16 22:51:12 2006 @@ -27,7 +27,10 @@ import org.apache.struts.action2.ServletActionContext; +import com.opensymphony.xwork.Action; import com.opensymphony.xwork.ActionInvocation; +import com.opensymphony.xwork.config.entities.ActionConfig; +import com.opensymphony.xwork.config.entities.ResultConfig; import com.opensymphony.xwork.interceptor.Interceptor; /** @@ -95,20 +98,28 @@ * The action invocation */ public String intercept(ActionInvocation invocation) throws Exception { - FacesContext facesContext = facesContextFactory.getFacesContext( - ServletActionContext.getServletContext(), ServletActionContext - .getRequest(), ServletActionContext.getResponse(), - lifecycle); - - setLifecycle(lifecycle); - - try { - return invocation.invoke(); - } finally { - facesContext.release(); - } + if (facesContextFactory != null && isFacesAction(invocation)) { + + invocation.getInvocationContext().put( + FacesInterceptor.FACES_ENABLED, Boolean.TRUE); + + FacesContext facesContext = facesContextFactory.getFacesContext( + ServletActionContext.getServletContext(), ServletActionContext + .getRequest(), ServletActionContext.getResponse(), + lifecycle); + + setLifecycle(lifecycle); + + try { + return invocation.invoke(); + } finally { + facesContext.release(); + } + } else { + return invocation.invoke(); + } } - + /** * Cleans up the lifecycle and factories */ @@ -116,4 +127,29 @@ facesContextFactory = null; lifecycle = null; } + + /** + * Determines if this action mapping will be have a JSF view + * + * @param inv The action invocation + * @return True if the JSF interceptors should fire + */ + protected boolean isFacesAction(ActionInvocation inv) { + ActionConfig config = inv.getProxy().getConfig(); + if (config != null) { + ResultConfig resultConfig = config.getResults().get(Action.SUCCESS); + Class resClass = null; + try { + resClass = Class.forName(resultConfig.getClassName()); + } catch (ClassNotFoundException ex) { + log.warn("Can't find result class, ignoring as a faces request", ex); + } + if (resClass != null) { + if (resClass.isAssignableFrom(FacesResult.class)) { + return true; + } + } + } + return false; + } }