SWF-301 - Make JSF managed beans accessible inside a flow definition using EL expressions.

This commit is contained in:
Jeremy Grelle
2008-04-22 20:45:22 +00:00
parent 84a43f2f26
commit cffd1889a5
2 changed files with 80 additions and 21 deletions

View File

@@ -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;
}
}

View File

@@ -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);
}
}