mirror of
https://github.com/apache/struts.git
synced 2026-08-05 22:56:59 +00:00
Merges JSF into Action 2, allowing JSF components and backing beans to
be able to be used along side regular saf2 actions. Furthermore, the familiar feel of an action-based framework is brought to JSF pages, giving each page its own action and making that action available in the component's expressions. This commit also includes a new section in the showcase, demonstrating the JSF support. WW-1320 git-svn-id: https://svn.apache.org/repos/asf/struts/action2/trunk@408129 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -83,6 +83,17 @@
|
||||
<version>1.2.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>myfaces</groupId>
|
||||
<artifactId>myfaces-impl</artifactId>
|
||||
<version>1.1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>myfaces</groupId>
|
||||
<artifactId>myfaces-api</artifactId>
|
||||
<version>1.1.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.apache.struts.action2.showcase.jsf;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Employee {
|
||||
private String name;
|
||||
private int id;
|
||||
private List skills;
|
||||
|
||||
public Employee() {}
|
||||
|
||||
public Employee(int id, String name, String[] skills) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.skills = Arrays.asList(skills);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public List getSkills() {
|
||||
return skills;
|
||||
}
|
||||
public void setSkills(List skills) {
|
||||
this.skills = skills;
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* $Id: QuizAction.java 394498 2006-04-16 15:28:06Z tmjee $
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.struts.action2.showcase.jsf;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
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 String execute() {
|
||||
this.employee = EmployeeDao.getEmployee(id);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
public String save() {
|
||||
EmployeeDao.save(employee);
|
||||
return "index";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.apache.struts.action2.showcase.jsf;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class EmployeeDao {
|
||||
|
||||
private static String[] skills;
|
||||
|
||||
private static List<Employee> employees;
|
||||
|
||||
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"}));
|
||||
|
||||
skills = new String[]{"Java", "PHP", "C#"};
|
||||
}
|
||||
|
||||
public static List<Employee> getEmployees() {
|
||||
return employees;
|
||||
}
|
||||
|
||||
public static Employee getEmployee(int id) {
|
||||
return employees.get(id);
|
||||
}
|
||||
|
||||
public static void save(Employee e) {
|
||||
employees.set(e.getId(), e);
|
||||
}
|
||||
|
||||
public static String[] getSkills() {
|
||||
return skills;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* $Id: QuizAction.java 394498 2006-04-16 15:28:06Z tmjee $
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.struts.action2.showcase.jsf;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
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 String execute() {
|
||||
System.out.println("executing");
|
||||
loadedEmployees = EmployeeDao.getEmployees();
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
|
||||
<xwork>
|
||||
<include file="struts-default.xml"/>
|
||||
|
||||
<package name="jsf" extends="struts-default" namespace="/jsf">
|
||||
|
||||
<action name="index" class="org.apache.struts.action2.showcase.jsf.IndexAction">
|
||||
<interceptor-ref name="jsfStack"/>
|
||||
<result name="success" type="jsf" />
|
||||
</action>
|
||||
|
||||
<action name="employee" class="org.apache.struts.action2.showcase.jsf.EmployeeAction">
|
||||
<interceptor-ref name="basicStack"/>
|
||||
<interceptor-ref name="jsfStack"/>
|
||||
<result name="success" type="jsf" />
|
||||
<result name="index" type="redirect-action">index</result>
|
||||
</action>
|
||||
|
||||
</package>
|
||||
|
||||
</xwork>
|
||||
@@ -23,6 +23,8 @@
|
||||
<include file="xwork-person.xml" />
|
||||
|
||||
<include file="xwork-wait.xml" />
|
||||
|
||||
<include file="xwork-jsf.xml" />
|
||||
|
||||
<include file="xwork-token.xml" />
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@
|
||||
<li><a href="<saf:url value="/wait/index.jsp"/>">Execute & Wait</a></li>
|
||||
<li><a href="<saf:url value="/token/index.jsp"/>">Token</a></li>
|
||||
<li><a href="<saf:url value="/filedownload/index.jsp"/>">File Download</a></li>
|
||||
<li><a href="<saf:url action="index" namespace="/jsf"/>">JSF</a></li>
|
||||
<li class="last"><a href="<saf:url value="/help.jsp"/>">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
<display-name>WebWork Showcase Application</display-name>
|
||||
|
||||
|
||||
<filter>
|
||||
<filter-name>action2-cleanup</filter-name>
|
||||
<filter-class>org.apache.struts.action2.dispatcher.ActionContextCleanUp</filter-class>
|
||||
@@ -18,6 +19,8 @@
|
||||
<filter-name>sitemesh</filter-name>
|
||||
<filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
|
||||
</filter>
|
||||
|
||||
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>action2-cleanup</filter-name>
|
||||
@@ -38,8 +41,13 @@
|
||||
<listener>
|
||||
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
||||
</listener>
|
||||
|
||||
|
||||
|
||||
<listener>
|
||||
<listener-class>
|
||||
org.apache.myfaces.webapp.StartupServletContextListener
|
||||
</listener-class>
|
||||
</listener>
|
||||
|
||||
<!-- SNIPPET START: dwr -->
|
||||
|
||||
<servlet>
|
||||
@@ -50,6 +58,19 @@
|
||||
<param-value>true</param-value>
|
||||
</init-param>
|
||||
</servlet>
|
||||
|
||||
<!-- JavaServer Faces Servlet Configuration, not used directly -->
|
||||
<servlet>
|
||||
<servlet-name>faces</servlet-name>
|
||||
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<!-- JavaServer Faces Servlet Mapping, not called directly -->
|
||||
<servlet-mapping>
|
||||
<servlet-name>faces</servlet-name>
|
||||
<url-pattern>*.action</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>dwr</servlet-name>
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
<%--
|
||||
|
||||
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>
|
||||
|
||||
<h2>Modify Employee</h2>
|
||||
|
||||
<h:form>
|
||||
<h:inputHidden value="#{action.employee.id}" />
|
||||
<h:panelGrid columns="2">
|
||||
<h:outputText value="ID:" />
|
||||
<h:outputText value="#{action.employee.id}" />
|
||||
<h:outputText value="Name:" />
|
||||
<h:inputText size="30" value="#{action.employee.name}" />
|
||||
<h:outputText value="Skills:" />
|
||||
<h:selectManyCheckbox 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:panelGrid>
|
||||
|
||||
<h:commandButton value="Submit" action="#{action.save}" />
|
||||
<br /><br />
|
||||
<h:outputLink value="index.action">
|
||||
<h:outputText value="Back" />
|
||||
</h:outputLink>
|
||||
</h:form>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
</f:view>
|
||||
@@ -0,0 +1,68 @@
|
||||
<%--
|
||||
|
||||
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>
|
||||
<h2>JSF Integration Examples</h2>
|
||||
<p>
|
||||
The following pages show how Struts Action 2 and JSF components can work together,
|
||||
each doing what they do best.
|
||||
</p>
|
||||
|
||||
<h3>Employee List</h3>
|
||||
|
||||
<h:dataTable value="#{action.employees}" var="e">
|
||||
<h:column>
|
||||
<f:facet name="header">
|
||||
<h:outputText value="ID" />
|
||||
</f:facet>
|
||||
<h:outputLink value="employee.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>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
</f:view>
|
||||
@@ -258,6 +258,13 @@
|
||||
<version>1.2.6</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>myfaces</groupId>
|
||||
<artifactId>myfaces-jsf-api</artifactId>
|
||||
<version>1.0.9</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* $Id: TokenInterceptor.java 394468 2006-04-16 12:16:03Z tmjee $
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.struts.action2.jsf;
|
||||
|
||||
import javax.faces.FacesException;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.event.PhaseId;
|
||||
|
||||
/**
|
||||
* Applies the request values to the component tree
|
||||
*/
|
||||
public class ApplyRequestValuesInterceptor extends FacesInterceptor {
|
||||
|
||||
private static final long serialVersionUID = -1471180154211835323L;
|
||||
|
||||
/**
|
||||
* Apply Request Values (JSF.2.2.2)
|
||||
*
|
||||
* @param viewId The view id
|
||||
* @param facesContext The faces context
|
||||
* @return true, if response is complete
|
||||
*/
|
||||
protected boolean executePhase(String viewId, FacesContext facesContext)
|
||||
throws FacesException {
|
||||
boolean skipFurtherProcessing = false;
|
||||
if (log.isTraceEnabled())
|
||||
log.trace("entering applyRequestValues");
|
||||
|
||||
informPhaseListenersBefore(facesContext, PhaseId.APPLY_REQUEST_VALUES);
|
||||
|
||||
if (isResponseComplete(facesContext, "applyRequestValues", true)) {
|
||||
// have to return right away
|
||||
return true;
|
||||
}
|
||||
if (shouldRenderResponse(facesContext, "applyRequestValues", true)) {
|
||||
skipFurtherProcessing = true;
|
||||
}
|
||||
|
||||
facesContext.getViewRoot().processDecodes(facesContext);
|
||||
|
||||
informPhaseListenersAfter(facesContext, PhaseId.APPLY_REQUEST_VALUES);
|
||||
|
||||
if (isResponseComplete(facesContext, "applyRequestValues", false)
|
||||
|| shouldRenderResponse(facesContext, "applyRequestValues",
|
||||
false)) {
|
||||
// since this phase is completed we don't need to return right away
|
||||
// even if the response is completed
|
||||
skipFurtherProcessing = true;
|
||||
}
|
||||
|
||||
if (!skipFurtherProcessing && log.isTraceEnabled())
|
||||
log.trace("exiting applyRequestValues");
|
||||
return skipFurtherProcessing;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* $Id: TokenInterceptor.java 394468 2006-04-16 12:16:03Z tmjee $
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.struts.action2.jsf;
|
||||
|
||||
import javax.faces.context.FacesContext;
|
||||
|
||||
import com.opensymphony.xwork.ActionInvocation;
|
||||
import com.opensymphony.xwork.interceptor.Interceptor;
|
||||
|
||||
/**
|
||||
* Translates JSF phases into individual interceptors, and adapts their expected
|
||||
* workflow to Action 2
|
||||
*/
|
||||
public class FacesInterceptor extends FacesSupport implements Interceptor {
|
||||
|
||||
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() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* $Id: PlainTextResult.java 394468 2006-04-16 12:16:03Z tmjee $
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.struts.action2.jsf;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.faces.FacesException;
|
||||
import javax.faces.application.Application;
|
||||
import javax.faces.application.ViewHandler;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.event.PhaseId;
|
||||
|
||||
import com.opensymphony.xwork.ActionInvocation;
|
||||
import com.opensymphony.xwork.Result;
|
||||
|
||||
/**
|
||||
* Executes the JSF render phase
|
||||
*/
|
||||
public class FacesResult extends FacesSupport implements Result {
|
||||
|
||||
private static final long serialVersionUID = -3548970638740937804L;
|
||||
|
||||
/**
|
||||
* Executes the result
|
||||
*/
|
||||
public void execute(ActionInvocation invocation) throws Exception {
|
||||
render(FacesContext.getCurrentInstance());
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the render phase, borrowed from MyFaces
|
||||
*
|
||||
* @param facesContext
|
||||
* The faces context
|
||||
* @throws FacesException
|
||||
* If anything goes wrong
|
||||
*/
|
||||
public void render(FacesContext facesContext) throws FacesException {
|
||||
// if the response is complete we should not be invoking the phase
|
||||
// listeners
|
||||
if (isResponseComplete(facesContext, "render", true)) {
|
||||
return;
|
||||
}
|
||||
if (log.isTraceEnabled())
|
||||
log.trace("entering renderResponse");
|
||||
|
||||
informPhaseListenersBefore(facesContext, PhaseId.RENDER_RESPONSE);
|
||||
// also possible that one of the listeners completed the response
|
||||
if (isResponseComplete(facesContext, "render", true)) {
|
||||
return;
|
||||
}
|
||||
Application application = facesContext.getApplication();
|
||||
ViewHandler viewHandler = application.getViewHandler();
|
||||
try {
|
||||
viewHandler.renderView(facesContext, facesContext.getViewRoot());
|
||||
} catch (IOException e) {
|
||||
throw new FacesException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
informPhaseListenersAfter(facesContext, PhaseId.RENDER_RESPONSE);
|
||||
if (log.isTraceEnabled()) {
|
||||
// Note: DebugUtils Logger must also be in trace level
|
||||
// DebugUtils.traceView("View after rendering");
|
||||
}
|
||||
|
||||
if (log.isTraceEnabled())
|
||||
log.trace("exiting renderResponse");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* $Id: TokenInterceptor.java 394468 2006-04-16 12:16:03Z tmjee $
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.struts.action2.jsf;
|
||||
|
||||
import javax.faces.FactoryFinder;
|
||||
import javax.faces.application.Application;
|
||||
import javax.faces.application.ApplicationFactory;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.context.FacesContextFactory;
|
||||
import javax.faces.lifecycle.Lifecycle;
|
||||
import javax.faces.lifecycle.LifecycleFactory;
|
||||
|
||||
import org.apache.struts.action2.ServletActionContext;
|
||||
|
||||
import com.opensymphony.xwork.ActionInvocation;
|
||||
import com.opensymphony.xwork.interceptor.Interceptor;
|
||||
|
||||
/**
|
||||
* Initializes the JSF context for this request
|
||||
*/
|
||||
public class FacesSetupInterceptor extends FacesSupport implements Interceptor {
|
||||
|
||||
private static final long serialVersionUID = -621512342655103941L;
|
||||
|
||||
private String lifecycleId = LifecycleFactory.DEFAULT_LIFECYCLE;
|
||||
|
||||
private FacesContextFactory facesContextFactory;
|
||||
|
||||
private Lifecycle lifecycle;
|
||||
|
||||
/**
|
||||
* Sets the lifecycle id
|
||||
*
|
||||
* @param id
|
||||
* The id
|
||||
*/
|
||||
public void setLifecycleId(String id) {
|
||||
this.lifecycleId = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the lifecycle and factories
|
||||
*/
|
||||
public void init() {
|
||||
facesContextFactory = (FacesContextFactory) FactoryFinder
|
||||
.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
|
||||
// Javadoc says: Lifecycle instance is shared across multiple
|
||||
// simultaneous requests, it must be implemented in a thread-safe
|
||||
// manner.
|
||||
// So we can acquire it here once:
|
||||
LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder
|
||||
.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
|
||||
lifecycle = lifecycleFactory.getLifecycle(lifecycleId);
|
||||
|
||||
Application application = ((ApplicationFactory) FactoryFinder
|
||||
.getFactory(FactoryFinder.APPLICATION_FACTORY))
|
||||
.getApplication();
|
||||
if (!(application.getNavigationHandler() instanceof StrutsNavigationHandler)) {
|
||||
application.setNavigationHandler(new StrutsNavigationHandler());
|
||||
}
|
||||
if (!(application.getVariableResolver() instanceof StrutsVariableResolver)) {
|
||||
application.setVariableResolver(new StrutsVariableResolver(
|
||||
application.getVariableResolver()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the faces context for other phases.
|
||||
*
|
||||
* @param invocation
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up the lifecycle and factories
|
||||
*/
|
||||
public void destroy() {
|
||||
facesContextFactory = null;
|
||||
lifecycle = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* $Id: TokenInterceptor.java 394468 2006-04-16 12:16:03Z tmjee $
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.struts.action2.jsf;
|
||||
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.event.PhaseEvent;
|
||||
import javax.faces.event.PhaseId;
|
||||
import javax.faces.event.PhaseListener;
|
||||
import javax.faces.lifecycle.Lifecycle;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.opensymphony.xwork.ActionContext;
|
||||
|
||||
/**
|
||||
* Provides common lifecycle phase methods needed by interceptors and results.
|
||||
*/
|
||||
public class FacesSupport {
|
||||
|
||||
private static final String LIFECYCLE_KEY = "lifecycle";
|
||||
|
||||
/** Log instance for each class */
|
||||
protected Log log;
|
||||
|
||||
/** Initializes log instance for the instance object */
|
||||
protected FacesSupport() {
|
||||
log = LogFactory.getLog(getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the shared lifecycle for this request
|
||||
*
|
||||
* @return The lifecycle
|
||||
*/
|
||||
private Lifecycle getLifecycle() {
|
||||
return (Lifecycle) ActionContext.getContext().get(LIFECYCLE_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the lifecycle for this request
|
||||
*
|
||||
* @param lifecycle
|
||||
* The lifecycle
|
||||
*/
|
||||
protected void setLifecycle(Lifecycle lifecycle) {
|
||||
ActionContext.getContext().put(LIFECYCLE_KEY, lifecycle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs phase listeners before a phase is executed
|
||||
*
|
||||
* @param facesContext
|
||||
* The current faces context
|
||||
* @param phaseId
|
||||
* The phase id about to be executed
|
||||
*/
|
||||
protected void informPhaseListenersBefore(FacesContext facesContext,
|
||||
PhaseId phaseId) {
|
||||
Lifecycle lifecycle = getLifecycle();
|
||||
PhaseListener[] phaseListeners = lifecycle.getPhaseListeners();
|
||||
for (int i = 0; i < phaseListeners.length; i++) {
|
||||
PhaseListener phaseListener = phaseListeners[i];
|
||||
int listenerPhaseId = phaseListener.getPhaseId().getOrdinal();
|
||||
if (listenerPhaseId == PhaseId.ANY_PHASE.getOrdinal()
|
||||
|| listenerPhaseId == phaseId.getOrdinal()) {
|
||||
phaseListener.beforePhase(new PhaseEvent(FacesContext
|
||||
.getCurrentInstance(), phaseId, lifecycle));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs phase listeners after a phase is executed
|
||||
*
|
||||
* @param facesContext
|
||||
* The current faces context
|
||||
* @param phaseId
|
||||
* The phase id that was executed
|
||||
*/
|
||||
protected void informPhaseListenersAfter(FacesContext facesContext,
|
||||
PhaseId phaseId) {
|
||||
Lifecycle lifecycle = getLifecycle();
|
||||
PhaseListener[] phaseListeners = lifecycle.getPhaseListeners();
|
||||
for (int i = 0; i < phaseListeners.length; i++) {
|
||||
PhaseListener phaseListener = phaseListeners[i];
|
||||
int listenerPhaseId = phaseListener.getPhaseId().getOrdinal();
|
||||
if (listenerPhaseId == PhaseId.ANY_PHASE.getOrdinal()
|
||||
|| listenerPhaseId == phaseId.getOrdinal()) {
|
||||
phaseListener.afterPhase(new PhaseEvent(FacesContext
|
||||
.getCurrentInstance(), phaseId, lifecycle));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the response has been completed. Mainly used for better
|
||||
* debugging messages.
|
||||
*
|
||||
* @param facesContext
|
||||
* The current faces context
|
||||
* @param phase
|
||||
* The phase id in execution
|
||||
* @param before
|
||||
* Whether the phase has been executed or not
|
||||
* @return True if the response is complete
|
||||
*/
|
||||
protected boolean isResponseComplete(FacesContext facesContext,
|
||||
String phase, boolean before) {
|
||||
boolean flag = false;
|
||||
if (facesContext.getResponseComplete()) {
|
||||
if (log.isDebugEnabled())
|
||||
log
|
||||
.debug("exiting from lifecycle.execute in "
|
||||
+ phase
|
||||
+ " because getResponseComplete is true from one of the "
|
||||
+ (before ? "before" : "after") + " listeners");
|
||||
flag = true;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see the render phase should be executed next. Mainly used for
|
||||
* better debugging messages.
|
||||
*
|
||||
* @param facesContext
|
||||
* The current faces context
|
||||
* @param phase
|
||||
* The phase id in execution
|
||||
* @param before
|
||||
* Whether the phase has been executed or not
|
||||
* @return True if the response is complete
|
||||
*/
|
||||
protected boolean shouldRenderResponse(FacesContext facesContext,
|
||||
String phase, boolean before) {
|
||||
boolean flag = false;
|
||||
if (facesContext.getRenderResponse()) {
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("exiting from lifecycle.execute in " + phase
|
||||
+ " because getRenderResponse is true from one of the "
|
||||
+ (before ? "before" : "after") + " listeners");
|
||||
flag = true;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* $Id: TokenInterceptor.java 394468 2006-04-16 12:16:03Z tmjee $
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.struts.action2.jsf;
|
||||
|
||||
import javax.faces.FacesException;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.event.PhaseId;
|
||||
|
||||
/**
|
||||
* Invokes the application
|
||||
*/
|
||||
public class InvokeApplicationInterceptor extends FacesInterceptor {
|
||||
|
||||
private static final long serialVersionUID = -7388153356410171208L;
|
||||
|
||||
/**
|
||||
* Invoke Application (JSF.2.2.5)
|
||||
*
|
||||
* @param viewId
|
||||
* The view id
|
||||
* @param facesContext
|
||||
* The faces context
|
||||
* @return true, if response is complete
|
||||
*/
|
||||
protected boolean executePhase(String viewId, FacesContext facesContext)
|
||||
throws FacesException {
|
||||
boolean skipFurtherProcessing = false;
|
||||
if (log.isTraceEnabled())
|
||||
log.trace("entering invokeApplication");
|
||||
|
||||
informPhaseListenersBefore(facesContext, PhaseId.INVOKE_APPLICATION);
|
||||
|
||||
if (isResponseComplete(facesContext, "invokeApplication", true)) {
|
||||
// have to return right away
|
||||
return true;
|
||||
}
|
||||
if (shouldRenderResponse(facesContext, "invokeApplication", true)) {
|
||||
skipFurtherProcessing = true;
|
||||
}
|
||||
|
||||
facesContext.getViewRoot().processApplication(facesContext);
|
||||
|
||||
informPhaseListenersAfter(facesContext, PhaseId.INVOKE_APPLICATION);
|
||||
|
||||
if (isResponseComplete(facesContext, "invokeApplication", false)
|
||||
|| shouldRenderResponse(facesContext, "invokeApplication",
|
||||
false)) {
|
||||
// since this phase is completed we don't need to return right away
|
||||
// even if the response is completed
|
||||
skipFurtherProcessing = true;
|
||||
}
|
||||
|
||||
if (!skipFurtherProcessing && log.isTraceEnabled())
|
||||
log.trace("exiting invokeApplication ");
|
||||
|
||||
return skipFurtherProcessing;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* $Id: TokenInterceptor.java 394468 2006-04-16 12:16:03Z tmjee $
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.struts.action2.jsf;
|
||||
|
||||
import javax.faces.FacesException;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.event.PhaseId;
|
||||
|
||||
/**
|
||||
* Processes validations on the component tree
|
||||
*/
|
||||
public class ProcessValidationsInterceptor extends FacesInterceptor {
|
||||
|
||||
private static final long serialVersionUID = 8785236570688278147L;
|
||||
|
||||
/**
|
||||
* Process Validations (JSF.2.2.3)
|
||||
*
|
||||
* @param viewId
|
||||
* The view id
|
||||
* @param facesContext
|
||||
* The faces context
|
||||
* @return true, if response is complete
|
||||
*/
|
||||
protected boolean executePhase(String viewId, FacesContext facesContext)
|
||||
throws FacesException {
|
||||
boolean skipFurtherProcessing = false;
|
||||
if (log.isTraceEnabled())
|
||||
log.trace("entering processValidations");
|
||||
|
||||
informPhaseListenersBefore(facesContext, PhaseId.PROCESS_VALIDATIONS);
|
||||
|
||||
if (isResponseComplete(facesContext, "processValidations", true)) {
|
||||
// have to return right away
|
||||
return true;
|
||||
}
|
||||
if (shouldRenderResponse(facesContext, "processValidations", true)) {
|
||||
skipFurtherProcessing = true;
|
||||
}
|
||||
|
||||
facesContext.getViewRoot().processValidators(facesContext);
|
||||
|
||||
informPhaseListenersAfter(facesContext, PhaseId.PROCESS_VALIDATIONS);
|
||||
|
||||
if (isResponseComplete(facesContext, "processValidations", false)
|
||||
|| shouldRenderResponse(facesContext, "processValidations",
|
||||
false)) {
|
||||
// since this phase is completed we don't need to return right away
|
||||
// even if the response is completed
|
||||
skipFurtherProcessing = true;
|
||||
}
|
||||
|
||||
if (!skipFurtherProcessing && log.isTraceEnabled())
|
||||
log.trace("exiting processValidations");
|
||||
return skipFurtherProcessing;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* $Id: TokenInterceptor.java 394468 2006-04-16 12:16:03Z tmjee $
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.struts.action2.jsf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.faces.FacesException;
|
||||
import javax.faces.application.Application;
|
||||
import javax.faces.application.ViewHandler;
|
||||
import javax.faces.component.UIComponent;
|
||||
import javax.faces.component.UIInput;
|
||||
import javax.faces.component.UIViewRoot;
|
||||
import javax.faces.context.ExternalContext;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.el.ValueBinding;
|
||||
import javax.faces.event.PhaseId;
|
||||
|
||||
/**
|
||||
* Restores the view or component tree
|
||||
*/
|
||||
public class RestoreViewInterceptor extends FacesInterceptor {
|
||||
|
||||
private static final long serialVersionUID = -1500785113037140668L;
|
||||
|
||||
/**
|
||||
* Restore View (JSF.2.2.1)
|
||||
*
|
||||
* @param viewId
|
||||
* The view id
|
||||
* @param facesContext
|
||||
* The faces context
|
||||
* @return true, if immediate rendering should occur
|
||||
*/
|
||||
protected boolean executePhase(String viewId, FacesContext facesContext) {
|
||||
boolean skipFurtherProcessing = false;
|
||||
if (log.isTraceEnabled())
|
||||
log.trace("entering restoreView");
|
||||
|
||||
informPhaseListenersBefore(facesContext, PhaseId.RESTORE_VIEW);
|
||||
|
||||
if (isResponseComplete(facesContext, "restoreView", true)) {
|
||||
// have to skips this phase
|
||||
return true;
|
||||
}
|
||||
if (shouldRenderResponse(facesContext, "restoreView", true)) {
|
||||
skipFurtherProcessing = true;
|
||||
}
|
||||
|
||||
ExternalContext externalContext = facesContext.getExternalContext();
|
||||
String defaultSuffix = externalContext
|
||||
.getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME);
|
||||
String suffix = defaultSuffix != null ? defaultSuffix
|
||||
: ViewHandler.DEFAULT_SUFFIX;
|
||||
if (viewId != null) {
|
||||
viewId += suffix;
|
||||
}
|
||||
|
||||
if (viewId == null) {
|
||||
if (!externalContext.getRequestServletPath().endsWith("/")) {
|
||||
try {
|
||||
externalContext.redirect(externalContext
|
||||
.getRequestServletPath()
|
||||
+ "/");
|
||||
facesContext.responseComplete();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
throw new FacesException("redirect failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Application application = facesContext.getApplication();
|
||||
ViewHandler viewHandler = application.getViewHandler();
|
||||
|
||||
// boolean viewCreated = false;
|
||||
UIViewRoot viewRoot = viewHandler.restoreView(facesContext, viewId);
|
||||
if (viewRoot == null) {
|
||||
viewRoot = viewHandler.createView(facesContext, viewId);
|
||||
viewRoot.setViewId(viewId);
|
||||
facesContext.renderResponse();
|
||||
// viewCreated = true;
|
||||
}
|
||||
|
||||
facesContext.setViewRoot(viewRoot);
|
||||
|
||||
/*
|
||||
* This section has been disabled because it causes some bug. Be careful
|
||||
* if you need to re-enable it. Furthermore, for an unknown reason, it
|
||||
* seems that by default it is executed (i.e. log.isTraceEnabled() is
|
||||
* true). Bug example : This traceView causes DebugUtil.printComponent
|
||||
* to print all the attributes of the view components. And if you have a
|
||||
* data table within an aliasBean, this causes the data table to
|
||||
* initialize it's value attribute while the alias isn't set. So, the
|
||||
* value initializes with an UIData.EMPTY_DATA_MODEL, and not with the
|
||||
* aliased one. But as it's initialized, it will not try to get the
|
||||
* value from the ValueBinding next time it needs to. I expect this to
|
||||
* cause more similar bugs. TODO : Completely remove or be SURE by
|
||||
* default it's not executed, and it has no more side-effects.
|
||||
*
|
||||
* if (log.isTraceEnabled()) { //Note: DebugUtils Logger must also be in
|
||||
* trace level DebugUtils.traceView(viewCreated ? "Newly created view" :
|
||||
* "Restored view"); }
|
||||
*/
|
||||
|
||||
if (facesContext.getExternalContext().getRequestParameterMap()
|
||||
.isEmpty()) {
|
||||
// no POST or query parameters --> set render response flag
|
||||
facesContext.renderResponse();
|
||||
}
|
||||
|
||||
recursivelyHandleComponentReferencesAndSetValid(facesContext, viewRoot);
|
||||
|
||||
informPhaseListenersAfter(facesContext, PhaseId.RESTORE_VIEW);
|
||||
|
||||
if (isResponseComplete(facesContext, "restoreView", false)
|
||||
|| shouldRenderResponse(facesContext, "restoreView", false)) {
|
||||
// since this phase is completed we don't need to return right away
|
||||
// even if the response is completed
|
||||
skipFurtherProcessing = true;
|
||||
}
|
||||
|
||||
if (!skipFurtherProcessing && log.isTraceEnabled())
|
||||
log.trace("exiting restoreView ");
|
||||
return skipFurtherProcessing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Walk the component tree, executing any component-bindings to reattach
|
||||
* components to their backing beans. Also, any UIInput component is marked
|
||||
* as Valid.
|
||||
* <p>
|
||||
* Note that this method effectively breaks encapsulation; instead of asking
|
||||
* each component to update itself and its children, this method just
|
||||
* reaches into each component. That makes it impossible for any component
|
||||
* to customise its behaviour at this point.
|
||||
* <p>
|
||||
* This has been filed as an issue against the spec. Until this issue is
|
||||
* resolved, we'll add a new marker-interface for components to allow them
|
||||
* to define their interest in handling children bindings themselves.
|
||||
*/
|
||||
protected void recursivelyHandleComponentReferencesAndSetValid(
|
||||
FacesContext facesContext, UIComponent parent) {
|
||||
recursivelyHandleComponentReferencesAndSetValid(facesContext, parent,
|
||||
false);
|
||||
}
|
||||
|
||||
protected void recursivelyHandleComponentReferencesAndSetValid(
|
||||
FacesContext facesContext, UIComponent parent, boolean forceHandle) {
|
||||
Method handleBindingsMethod = getBindingMethod(parent);
|
||||
|
||||
if (handleBindingsMethod != null && !forceHandle) {
|
||||
try {
|
||||
handleBindingsMethod.invoke(parent, new Object[] {});
|
||||
} catch (Throwable th) {
|
||||
log.error(
|
||||
"Exception while invoking handleBindings on component with client-id:"
|
||||
+ parent.getClientId(facesContext), th);
|
||||
}
|
||||
} else {
|
||||
for (Iterator it = parent.getFacetsAndChildren(); it.hasNext();) {
|
||||
UIComponent component = (UIComponent) it.next();
|
||||
|
||||
ValueBinding binding = component.getValueBinding("binding"); // TODO:
|
||||
// constant
|
||||
if (binding != null && !binding.isReadOnly(facesContext)) {
|
||||
binding.setValue(facesContext, component);
|
||||
}
|
||||
|
||||
if (component instanceof UIInput) {
|
||||
((UIInput) component).setValid(true);
|
||||
}
|
||||
|
||||
recursivelyHandleComponentReferencesAndSetValid(facesContext,
|
||||
component);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is all a hack to work around a spec-bug which will be fixed in
|
||||
* JSF2.0
|
||||
*
|
||||
* @param parent
|
||||
* @return true if this component is bindingAware (e.g. aliasBean)
|
||||
*/
|
||||
private static Method getBindingMethod(UIComponent parent) {
|
||||
Class[] clazzes = parent.getClass().getInterfaces();
|
||||
|
||||
for (int i = 0; i < clazzes.length; i++) {
|
||||
Class clazz = clazzes[i];
|
||||
|
||||
if (clazz.getName().indexOf("BindingAware") != -1) {
|
||||
try {
|
||||
return parent.getClass().getMethod("handleBindings",
|
||||
new Class[] {});
|
||||
} catch (NoSuchMethodException e) {
|
||||
// return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* $Id: TokenInterceptor.java 394468 2006-04-16 12:16:03Z tmjee $
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.struts.action2.jsf;
|
||||
|
||||
import javax.faces.application.NavigationHandler;
|
||||
import javax.faces.context.FacesContext;
|
||||
|
||||
import com.opensymphony.xwork.ActionContext;
|
||||
|
||||
/**
|
||||
* Overrides the JFS navigation by delegating the result to handling by the core
|
||||
* result code lookup and execution.
|
||||
*/
|
||||
public class StrutsNavigationHandler extends NavigationHandler {
|
||||
|
||||
/**
|
||||
* Stores any outcomes as the result code
|
||||
*
|
||||
* @param facesContext The faces context
|
||||
* @param fromAction The action we are coming from
|
||||
* @param outcome The String return code
|
||||
*/
|
||||
@Override
|
||||
public void handleNavigation(FacesContext facesContext, String fromAction, String outcome) {
|
||||
ActionContext ctx = ActionContext.getContext();
|
||||
if (outcome != null) {
|
||||
ctx.getActionInvocation().setResultCode(outcome);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* $Id: TokenInterceptor.java 394468 2006-04-16 12:16:03Z tmjee $
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.struts.action2.jsf;
|
||||
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.el.EvaluationException;
|
||||
import javax.faces.el.VariableResolver;
|
||||
|
||||
import com.opensymphony.xwork.ActionContext;
|
||||
|
||||
/**
|
||||
* Adds the current Action instance to the variable lookups. All other requests
|
||||
* delegate to underlying resolver.
|
||||
*/
|
||||
public class StrutsVariableResolver extends VariableResolver {
|
||||
|
||||
/** The original <code>VariableResolver</code> passed to our constructor. */
|
||||
private VariableResolver original = null;
|
||||
|
||||
/** The variable name of our Struts action */
|
||||
private static final String STRUTS_VARIABLE_NAME = "action";
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param original
|
||||
* Original resolver to delegate to.
|
||||
*/
|
||||
public StrutsVariableResolver(VariableResolver original) {
|
||||
|
||||
this.original = original;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Resolve variable names known to this resolver; otherwise, delegate to the
|
||||
* original resolver passed to our constructor.
|
||||
* </p>
|
||||
*
|
||||
* @param name
|
||||
* Variable name to be resolved
|
||||
*/
|
||||
public Object resolveVariable(FacesContext context, String name)
|
||||
throws EvaluationException {
|
||||
|
||||
if (STRUTS_VARIABLE_NAME.equals(name)) {
|
||||
return ActionContext.getContext().getActionInvocation().getAction();
|
||||
} else {
|
||||
return original.resolveVariable(context, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* $Id: TokenInterceptor.java 394468 2006-04-16 12:16:03Z tmjee $
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.struts.action2.jsf;
|
||||
|
||||
import javax.faces.FacesException;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.event.PhaseId;
|
||||
|
||||
/**
|
||||
* Updates the model values from the component tree
|
||||
*/
|
||||
public class UpdateModelValuesInterceptor extends FacesInterceptor {
|
||||
|
||||
private static final long serialVersionUID = 4011504235094251077L;
|
||||
|
||||
/**
|
||||
* Update Model Values (JSF.2.2.4)
|
||||
*
|
||||
* @param viewId The view id
|
||||
* @param facesContext The faces context
|
||||
* @return true, if response is complete
|
||||
*/
|
||||
protected boolean executePhase(String viewId, FacesContext facesContext) throws FacesException
|
||||
{
|
||||
boolean skipFurtherProcessing = false;
|
||||
if (log.isTraceEnabled()) log.trace("entering updateModelValues");
|
||||
|
||||
informPhaseListenersBefore(facesContext, PhaseId.UPDATE_MODEL_VALUES);
|
||||
|
||||
if(isResponseComplete(facesContext, "updateModelValues", true))
|
||||
{
|
||||
// have to return right away
|
||||
return true;
|
||||
}
|
||||
if(shouldRenderResponse(facesContext, "updateModelValues", true))
|
||||
{
|
||||
skipFurtherProcessing = true;
|
||||
}
|
||||
|
||||
facesContext.getViewRoot().processUpdates(facesContext);
|
||||
|
||||
informPhaseListenersAfter(facesContext, PhaseId.UPDATE_MODEL_VALUES);
|
||||
|
||||
if (isResponseComplete(facesContext, "updateModelValues", false)
|
||||
|| shouldRenderResponse(facesContext, "updateModelValues", false))
|
||||
{
|
||||
// since this phase is completed we don't need to return right away even if the response is completed
|
||||
skipFurtherProcessing = true;
|
||||
}
|
||||
|
||||
if (!skipFurtherProcessing && log.isTraceEnabled()) log.trace("exiting updateModelValues");
|
||||
|
||||
return skipFurtherProcessing;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<body>
|
||||
Integrates the JSF library into the Struts Action Framework. The overall approach
|
||||
splits the JSF lifecycle into an Interceptor stack and Result, delegating
|
||||
navigation and general controller functions to Struts.
|
||||
<p>
|
||||
Most of this code was borrowed from MyFaces, and as such, will need to be synchronized
|
||||
occassionally with the original code.
|
||||
</p>
|
||||
</body>
|
||||
@@ -13,6 +13,7 @@
|
||||
<result-type name="velocity" class="org.apache.struts.action2.dispatcher.VelocityResult"/>
|
||||
<result-type name="xslt" class="org.apache.struts.action2.views.xslt.XSLTResult"/>
|
||||
<result-type name="plaintext" class="org.apache.struts.action2.dispatcher.PlainTextResult" />
|
||||
<result-type name="jsf" class="org.apache.struts.action2.jsf.FacesResult" />
|
||||
|
||||
<!-- third party integration -->
|
||||
<result-type name="jasper" class="org.apache.struts.action2.views.jasperreports.JasperReportsResult"/>
|
||||
@@ -44,6 +45,14 @@
|
||||
<interceptor name="token-session" class="org.apache.struts.action2.interceptor.TokenSessionStoreInterceptor"/>
|
||||
<interceptor name="validation" class="com.opensymphony.xwork.validator.ValidationInterceptor"/>
|
||||
<interceptor name="workflow" class="com.opensymphony.xwork.interceptor.DefaultWorkflowInterceptor"/>
|
||||
|
||||
<!-- JSF interceptors, one per lifecycle phase -->
|
||||
<interceptor class="org.apache.struts.action2.jsf.FacesSetupInterceptor" name="jsfSetup" />
|
||||
<interceptor class="org.apache.struts.action2.jsf.RestoreViewInterceptor" name="jsfRestore" />
|
||||
<interceptor class="org.apache.struts.action2.jsf.ApplyRequestValuesInterceptor" name="jsfApply" />
|
||||
<interceptor class="org.apache.struts.action2.jsf.ProcessValidationsInterceptor" name="jsfValidate" />
|
||||
<interceptor class="org.apache.struts.action2.jsf.UpdateModelValuesInterceptor" name="jsfUpdate" />
|
||||
<interceptor class="org.apache.struts.action2.jsf.InvokeApplicationInterceptor" name="jsfInvoke" />
|
||||
|
||||
<!-- Basic stack -->
|
||||
<interceptor-stack name="basicStack">
|
||||
@@ -176,6 +185,16 @@
|
||||
<interceptor-ref name="execAndWait">
|
||||
<param name="excludeMethods">input,back,cancel</param>
|
||||
</interceptor-ref>
|
||||
</interceptor-stack>
|
||||
|
||||
<!-- Sample JSF stack, can be combined with other stacks easily -->
|
||||
<interceptor-stack name="jsfStack">
|
||||
<interceptor-ref name="jsfSetup" />
|
||||
<interceptor-ref name="jsfRestore" />
|
||||
<interceptor-ref name="jsfApply" />
|
||||
<interceptor-ref name="jsfValidate" />
|
||||
<interceptor-ref name="jsfUpdate" />
|
||||
<interceptor-ref name="jsfInvoke" />
|
||||
</interceptor-stack>
|
||||
</interceptors>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user