SWF-301 - Make JSF managed beans accessible inside a flow definition using EL expressions.
This commit is contained in:
@@ -19,7 +19,10 @@ import java.util.Iterator;
|
||||
|
||||
import javax.el.ELContext;
|
||||
import javax.el.ELResolver;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.el.ValueBinding;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.execution.RequestContextHolder;
|
||||
|
||||
@@ -27,8 +30,8 @@ import org.springframework.webflow.execution.RequestContextHolder;
|
||||
* ELResolver that checks request, session, and application scopes for existing JSF-managed beans. This allows
|
||||
* traditional JSF-managed beans (defined in faces-config.xml) to be resolved through expressions in a flow definition.
|
||||
* The preferred approach is to instead use Spring to configure such beans, but this is meant to ease migration for
|
||||
* users with existing JSF artifacts. Note that this resolver does not have access to the JSF managed bean definitions
|
||||
* and will not trigger the bean's instantiation if it has not already been initialized by JSF.
|
||||
* users with existing JSF artifacts. This resolver will delegate to a temporary FacesContext so that JSF managed bean
|
||||
* initialization will be triggered if the bean has not already been initialized by JSF.
|
||||
*
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
@@ -44,16 +47,10 @@ public class JsfManagedBeanResolver extends ELResolver {
|
||||
|
||||
public Class getType(ELContext context, Object base, Object property) {
|
||||
if (base == null) {
|
||||
RequestContext requestContext = RequestContextHolder.getRequestContext();
|
||||
if (requestContext.getExternalContext().getRequestMap().contains(property.toString())) {
|
||||
Object bean = getFacesBean(property);
|
||||
if (bean != null) {
|
||||
context.setPropertyResolved(true);
|
||||
return requestContext.getExternalContext().getRequestMap().get(property.toString()).getClass();
|
||||
} else if (requestContext.getExternalContext().getSessionMap().contains(property.toString())) {
|
||||
context.setPropertyResolved(true);
|
||||
return requestContext.getExternalContext().getSessionMap().get(property.toString()).getClass();
|
||||
} else if (requestContext.getExternalContext().getApplicationMap().contains(property.toString())) {
|
||||
context.setPropertyResolved(true);
|
||||
return requestContext.getExternalContext().getApplicationMap().get(property.toString()).getClass();
|
||||
return bean.getClass();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -61,16 +58,10 @@ public class JsfManagedBeanResolver extends ELResolver {
|
||||
|
||||
public Object getValue(ELContext context, Object base, Object property) {
|
||||
if (base == null) {
|
||||
RequestContext requestContext = RequestContextHolder.getRequestContext();
|
||||
if (requestContext.getExternalContext().getRequestMap().contains(property.toString())) {
|
||||
Object bean = getFacesBean(property);
|
||||
if (bean != null) {
|
||||
context.setPropertyResolved(true);
|
||||
return requestContext.getExternalContext().getRequestMap().get(property.toString());
|
||||
} else if (requestContext.getExternalContext().getSessionMap().contains(property.toString())) {
|
||||
context.setPropertyResolved(true);
|
||||
return requestContext.getExternalContext().getSessionMap().get(property.toString());
|
||||
} else if (requestContext.getExternalContext().getApplicationMap().contains(property.toString())) {
|
||||
context.setPropertyResolved(true);
|
||||
return requestContext.getExternalContext().getApplicationMap().get(property.toString());
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -83,12 +74,14 @@ public class JsfManagedBeanResolver extends ELResolver {
|
||||
|| requestContext.getExternalContext().getSessionMap().contains(property.toString())
|
||||
|| requestContext.getExternalContext().getApplicationMap().contains(property.toString())) {
|
||||
context.setPropertyResolved(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a bean value if a corresponding key is found in one of the ExternalContext scopes.
|
||||
*/
|
||||
public void setValue(ELContext context, Object base, Object property, Object value) {
|
||||
if (base == null) {
|
||||
RequestContext requestContext = RequestContextHolder.getRequestContext();
|
||||
@@ -105,4 +98,33 @@ public class JsfManagedBeanResolver extends ELResolver {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This resolver is only meant to be called from the Flow Execution, thus it assumes that the FacesContext will not
|
||||
* be available and creates a temporary one on the fly.
|
||||
* @return The initialized FacesContext.
|
||||
*/
|
||||
private FacesContext getFacesContext() {
|
||||
RequestContext requestContext = RequestContextHolder.getRequestContext();
|
||||
Assert.notNull(requestContext, "RequestContext cannot be null - This resolver is only intended to be invoked "
|
||||
+ "from an active Flow Execution.");
|
||||
FacesContext facesContext = FlowFacesContext.newInstance(requestContext, FlowLifecycle.newInstance());
|
||||
return facesContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses a temporary FacesContext to try and resolve a JSF Managed Bean
|
||||
* @param beanName - The name of the bean to resolve.
|
||||
* @return The JSF Managed Bean instance if found.
|
||||
*/
|
||||
private Object getFacesBean(Object beanName) {
|
||||
FacesContext facesContext = getFacesContext();
|
||||
Object result = null;
|
||||
try {
|
||||
ValueBinding vb = facesContext.getApplication().createValueBinding("#{" + beanName + "}");
|
||||
result = vb.getValue(facesContext);
|
||||
} finally {
|
||||
facesContext.release();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.springframework.faces.webflow;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.jboss.el.ExpressionFactoryImpl;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.binding.expression.support.FluentParserContext;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.execution.RequestContextHolder;
|
||||
import org.springframework.webflow.test.MockRequestContext;
|
||||
|
||||
public class JsfManagedBeanAwareELExpressionParserTests extends TestCase {
|
||||
|
||||
JSFMockHelper jsfMock = new JSFMockHelper();
|
||||
|
||||
RequestContext requestContext = new MockRequestContext();
|
||||
|
||||
ExpressionParser parser;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
jsfMock.setUp();
|
||||
RequestContextHolder.setRequestContext(requestContext);
|
||||
parser = new JsfManagedBeanAwareELExpressionParser(new ExpressionFactoryImpl());
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
jsfMock.tearDown();
|
||||
}
|
||||
|
||||
public void testGetJSFBean() {
|
||||
jsfMock.externalContext().getRequestMap().put("myJsfBean", new Object());
|
||||
Expression expr = parser.parseExpression("myJsfBean", new FluentParserContext().evaluate(RequestContext.class));
|
||||
Object result = expr.getValue(requestContext);
|
||||
assertNotNull("The JSF Bean should not be null.", result);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user