- Revision
- 131
- Author
- mward
- Date
- 2007-06-02 00:18:11 -0500 (Sat, 02 Jun 2007)
Log Message
controller properties are now bound to the request attributes by their bean property name
Modified Paths
- trunk/core/src/main/java/org/codehaus/waffle/WaffleComponentRegistry.java
- trunk/core/src/main/java/org/codehaus/waffle/context/pico/PicoWaffleComponentRegistry.java
- trunk/core/src/main/java/org/codehaus/waffle/servlet/WaffleServlet.java
- trunk/core/src/test/java/org/codehaus/waffle/context/pico/PicoWaffleComponentRegistryTest.java
- trunk/core/src/test/java/org/codehaus/waffle/servlet/WaffleServletTest.java
Added Paths
- trunk/core/src/main/java/org/codehaus/waffle/bind/IntrospectingRequestAttributeBinder.java
- trunk/core/src/main/java/org/codehaus/waffle/bind/RequestAttributeBinder.java
- trunk/core/src/test/java/org/codehaus/waffle/bind/IntrospectingRequestAttributeBinderTest.java
- trunk/core/src/test/java/org/codehaus/waffle/testmodel/StubRequestAttributeBinder.java
Diff
Modified: trunk/core/src/main/java/org/codehaus/waffle/WaffleComponentRegistry.java (130 => 131)
--- trunk/core/src/main/java/org/codehaus/waffle/WaffleComponentRegistry.java 2007-06-02 04:16:01 UTC (rev 130) +++ trunk/core/src/main/java/org/codehaus/waffle/WaffleComponentRegistry.java 2007-06-02 05:18:11 UTC (rev 131) @@ -19,6 +19,7 @@ import org.codehaus.waffle.action.MethodNameResolver; import org.codehaus.waffle.bind.BindErrorMessageResolver; import org.codehaus.waffle.bind.DataBinder; +import org.codehaus.waffle.bind.RequestAttributeBinder; import org.codehaus.waffle.context.ContextContainerFactory; import org.codehaus.waffle.controller.ControllerDefinitionFactory; import org.codehaus.waffle.controller.ControllerNameResolver; @@ -66,6 +67,8 @@ Monitor getMonitor(); + RequestAttributeBinder getRequestAttributeBinder(); + TypeConverter getTypeConverter(); Validator getValidator();
Added: trunk/core/src/main/java/org/codehaus/waffle/bind/IntrospectingRequestAttributeBinder.java (0 => 131)
--- trunk/core/src/main/java/org/codehaus/waffle/bind/IntrospectingRequestAttributeBinder.java (rev 0) +++ trunk/core/src/main/java/org/codehaus/waffle/bind/IntrospectingRequestAttributeBinder.java 2007-06-02 05:18:11 UTC (rev 131) @@ -0,0 +1,35 @@ +package org.codehaus.waffle.bind; + +import org.codehaus.waffle.WaffleException; + +import javax.servlet.http.HttpServletRequest; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; + +public class IntrospectingRequestAttributeBinder implements RequestAttributeBinder { + + public void bind(HttpServletRequest request, Object controller) { + try { + BeanInfo beanInfo = Introspector.getBeanInfo(controller.getClass()); + PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); + + for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { + Method readMethod = propertyDescriptor.getReadMethod(); + // skip getClass() method and any get/is methods that take arguments + if (readMethod.getParameterTypes().length == 0 && !readMethod.getName().equals("getClass")) { + request.setAttribute(propertyDescriptor.getName(), readMethod.invoke(controller)); + } + } + } catch (IntrospectionException e) { + throw new WaffleException(e); + } catch (IllegalAccessException e) { + throw new WaffleException(e); + } catch (InvocationTargetException e) { + throw new WaffleException(e); + } + } +}
Added: trunk/core/src/main/java/org/codehaus/waffle/bind/RequestAttributeBinder.java (0 => 131)
--- trunk/core/src/main/java/org/codehaus/waffle/bind/RequestAttributeBinder.java (rev 0) +++ trunk/core/src/main/java/org/codehaus/waffle/bind/RequestAttributeBinder.java 2007-06-02 05:18:11 UTC (rev 131) @@ -0,0 +1,12 @@ +package org.codehaus.waffle.bind; + +import javax.servlet.http.HttpServletRequest; + +/** + * Implementors of this class allow for properties from a controller to be exposed as request attributes. This + * simplifies view development. + */ +public interface RequestAttributeBinder { + + void bind(HttpServletRequest request, Object controller); +}
Modified: trunk/core/src/main/java/org/codehaus/waffle/context/pico/PicoWaffleComponentRegistry.java (130 => 131)
--- trunk/core/src/main/java/org/codehaus/waffle/context/pico/PicoWaffleComponentRegistry.java 2007-06-02 04:16:01 UTC (rev 130) +++ trunk/core/src/main/java/org/codehaus/waffle/context/pico/PicoWaffleComponentRegistry.java 2007-06-02 05:18:11 UTC (rev 131) @@ -10,12 +10,7 @@ *****************************************************************************/ package org.codehaus.waffle.context.pico; -import java.util.Enumeration; - -import javax.servlet.ServletContext; - import ognl.TypeConverter; - import org.codehaus.waffle.WaffleComponentRegistry; import org.codehaus.waffle.WaffleException; import org.codehaus.waffle.action.ActionMethodExecutor; @@ -33,11 +28,13 @@ import org.codehaus.waffle.bind.DefaultBindErrorMessageResolver; import org.codehaus.waffle.bind.OgnlDataBinder; import org.codehaus.waffle.bind.OgnlTypeConverter; +import org.codehaus.waffle.bind.RequestAttributeBinder; +import org.codehaus.waffle.bind.IntrospectingRequestAttributeBinder; import org.codehaus.waffle.context.ContextContainerFactory; +import org.codehaus.waffle.controller.ContextControllerDefinitionFactory; +import org.codehaus.waffle.controller.ContextPathControllerNameResolver; import org.codehaus.waffle.controller.ControllerDefinitionFactory; import org.codehaus.waffle.controller.ControllerNameResolver; -import org.codehaus.waffle.controller.ContextControllerDefinitionFactory; -import org.codehaus.waffle.controller.ContextPathControllerNameResolver; import org.codehaus.waffle.i18n.DefaultMessageResources; import org.codehaus.waffle.i18n.MessageResources; import org.codehaus.waffle.monitor.ConsoleMonitor; @@ -55,6 +52,9 @@ import org.picocontainer.defaults.ConstructorInjectionComponentAdapter; import org.picocontainer.defaults.DefaultPicoContainer; +import javax.servlet.ServletContext; +import java.util.Enumeration; + /** * PicoContainer-based implementation of WaffleComponentRegistry * @@ -86,6 +86,7 @@ register(MethodDefinitionFinder.class, AnnotatedMethodDefinitionFinder.class, servletContext); register(MethodNameResolver.class, RequestParameterMethodNameResolver.class, servletContext); register(Monitor.class, ConsoleMonitor.class, servletContext); + register(RequestAttributeBinder.class, IntrospectingRequestAttributeBinder.class, servletContext); register(TypeConverter.class, OgnlTypeConverter.class, servletContext); register(Validator.class, DefaultValidator.class, servletContext); register(ViewDispatcher.class, DefaultViewDispatcher.class, servletContext); @@ -225,6 +226,10 @@ return locateByType(Monitor.class); } + public RequestAttributeBinder getRequestAttributeBinder() { + return locateByType(RequestAttributeBinder.class); + } + public TypeConverter getTypeConverter() { return locateByType(TypeConverter.class); }
Modified: trunk/core/src/main/java/org/codehaus/waffle/servlet/WaffleServlet.java (130 => 131)
--- trunk/core/src/main/java/org/codehaus/waffle/servlet/WaffleServlet.java 2007-06-02 04:16:01 UTC (rev 130) +++ trunk/core/src/main/java/org/codehaus/waffle/servlet/WaffleServlet.java 2007-06-02 05:18:11 UTC (rev 131) @@ -21,6 +21,7 @@ import org.codehaus.waffle.action.MethodDefinition; import org.codehaus.waffle.action.MethodInvocationException; import org.codehaus.waffle.bind.DataBinder; +import org.codehaus.waffle.bind.RequestAttributeBinder; import org.codehaus.waffle.controller.ControllerDefinition; import org.codehaus.waffle.controller.ControllerDefinitionFactory; import org.codehaus.waffle.validation.DefaultErrorsContext; @@ -48,6 +49,7 @@ private ActionMethodExecutor actionMethodExecutor; private ActionMethodResponseHandler actionMethodResponseHandler; private Validator validator; + private RequestAttributeBinder requestAttributeBinder; private String viewPrefix; private String viewSuffix; private boolean depsDone = false; @@ -60,12 +62,14 @@ DataBinder dataBinder, ActionMethodExecutor actionMethodExecutor, ActionMethodResponseHandler actionMethodResponseHandler, - Validator validator) { + Validator validator, + RequestAttributeBinder requestAttributeBinder) { this.controllerDefinitionFactory = controllerDefinitionFactory; this.dataBinder = dataBinder; this.actionMethodExecutor = actionMethodExecutor; this.actionMethodResponseHandler = actionMethodResponseHandler; this.validator = validator; + this.requestAttributeBinder = requestAttributeBinder; depsDone = true; } @@ -104,7 +108,6 @@ } return controllerDefinition; - } /** @@ -141,7 +144,7 @@ // TODO ... pluggable way to register controller instance variables to the request ... no longer have to do "controller.foobar" // pluggable cause we need to support ognl and ruby (get_instance_variables - + requestAttributeBinder.bind(request, controllerDefinition.getController()); actionMethodResponseHandler.handle(request, response, actionMethodResponse); } catch (MethodInvocationException e) { log(e.getMessage());
Added: trunk/core/src/test/java/org/codehaus/waffle/bind/IntrospectingRequestAttributeBinderTest.java (0 => 131)
--- trunk/core/src/test/java/org/codehaus/waffle/bind/IntrospectingRequestAttributeBinderTest.java (rev 0) +++ trunk/core/src/test/java/org/codehaus/waffle/bind/IntrospectingRequestAttributeBinderTest.java 2007-06-02 05:18:11 UTC (rev 131) @@ -0,0 +1,41 @@ +package org.codehaus.waffle.bind; + +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.jmock.integration.junit4.JMock; +import org.jmock.integration.junit4.JUnit4Mockery; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.servlet.http.HttpServletRequest; + [EMAIL PROTECTED](JMock.class) +public class IntrospectingRequestAttributeBinderTest { + private final Mockery context = new JUnit4Mockery(); + + @Test + public void allControllerPropertiesShouldBeBoundAsRequestAttributes() { + final HttpServletRequest request = context.mock(HttpServletRequest.class); + + context.checking(new Expectations() {{ + one (request).setAttribute("name", "my controller"); + one (request).setAttribute("null", null); + }}); + + IntrospectingRequestAttributeBinder binder = new IntrospectingRequestAttributeBinder(); + binder.bind(request, new SimpleController()); + } + + class SimpleController { + private String name = "my controller"; + + public String getName() { + return name; + } + + public Object getNull() { + return null; + } + } + +}
Modified: trunk/core/src/test/java/org/codehaus/waffle/context/pico/PicoWaffleComponentRegistryTest.java (130 => 131)
--- trunk/core/src/test/java/org/codehaus/waffle/context/pico/PicoWaffleComponentRegistryTest.java 2007-06-02 04:16:01 UTC (rev 130) +++ trunk/core/src/test/java/org/codehaus/waffle/context/pico/PicoWaffleComponentRegistryTest.java 2007-06-02 05:18:11 UTC (rev 131) @@ -1,17 +1,7 @@ package org.codehaus.waffle.context.pico; -import java.lang.reflect.Field; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.List; - -import javax.servlet.ServletContext; - import ognl.DefaultTypeConverter; import ognl.TypeConverter; - import org.codehaus.waffle.WaffleComponentRegistry; import org.codehaus.waffle.action.ActionMethodExecutor; import org.codehaus.waffle.action.ActionMethodResponseHandler; @@ -26,12 +16,13 @@ import org.codehaus.waffle.bind.DefaultBindErrorMessageResolver; import org.codehaus.waffle.bind.OgnlDataBinder; import org.codehaus.waffle.bind.OgnlTypeConverter; +import org.codehaus.waffle.bind.RequestAttributeBinder; import org.codehaus.waffle.context.AbstractContextContainerFactory; import org.codehaus.waffle.context.ContextContainerFactory; +import org.codehaus.waffle.controller.ContextControllerDefinitionFactory; +import org.codehaus.waffle.controller.ContextPathControllerNameResolver; import org.codehaus.waffle.controller.ControllerDefinitionFactory; import org.codehaus.waffle.controller.ControllerNameResolver; -import org.codehaus.waffle.controller.ContextControllerDefinitionFactory; -import org.codehaus.waffle.controller.ContextPathControllerNameResolver; import org.codehaus.waffle.i18n.DefaultMessageResources; import org.codehaus.waffle.i18n.MessageResources; import org.codehaus.waffle.monitor.ConsoleMonitor; @@ -52,6 +43,7 @@ import org.codehaus.waffle.testmodel.StubValidator; import org.codehaus.waffle.testmodel.StubViewDispatcher; import org.codehaus.waffle.testmodel.StubViewResolver; +import org.codehaus.waffle.testmodel.StubRequestAttributeBinder; import org.codehaus.waffle.validation.DefaultValidator; import org.codehaus.waffle.validation.Validator; import org.codehaus.waffle.view.DefaultDispatchAssistant; @@ -64,6 +56,14 @@ import org.jmock.MockObjectTestCase; import org.picocontainer.MutablePicoContainer; +import javax.servlet.ServletContext; +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; + public class PicoWaffleComponentRegistryTest extends MockObjectTestCase { @SuppressWarnings({"unchecked"}) private static final Enumeration EMPTY_ENUMERATION = Collections.enumeration(Collections.EMPTY_LIST); @@ -97,7 +97,7 @@ mockServletContext.expects(once()) .method("getInitParameterNames") .will(returnValue(EMPTY_ENUMERATION)); - mockServletContext.expects(exactly(17)) + mockServletContext.expects(exactly(18)) .method("getInitParameter") .will(returnValue(null)); ServletContext servletContext = (ServletContext) mockServletContext.proxy(); @@ -176,6 +176,9 @@ mockServletContext.expects(once()).method("getInitParameter") .with(eq(Monitor.class.getName())) .will(returnValue(StubMonitor.class.getName())); + mockServletContext.expects(once()).method("getInitParameter") + .with(eq(RequestAttributeBinder.class.getName())) + .will(returnValue(StubRequestAttributeBinder.class.getName())); ServletContext servletContext = (ServletContext) mockServletContext.proxy(); WaffleComponentRegistry componentRegistry = new PicoWaffleComponentRegistry(servletContext); @@ -193,6 +196,7 @@ assertTrue(componentRegistry.getActionMethodResponseHandler() instanceof StubActionMethodResponseHandler); assertTrue(componentRegistry.getMessageResources() instanceof StubMessageResources); assertTrue(componentRegistry.getMonitor() instanceof StubMonitor); + assertTrue(componentRegistry.getRequestAttributeBinder() instanceof StubRequestAttributeBinder); assertTrue(componentRegistry.getTypeConverter() instanceof DefaultTypeConverter); assertTrue(componentRegistry.getValidator() instanceof StubValidator); assertTrue(componentRegistry.getViewDispatcher() instanceof StubViewDispatcher); @@ -207,7 +211,7 @@ mockServletContext.expects(once()) .method("getInitParameterNames") .will(returnValue(Collections.enumeration(names))); - mockServletContext.expects(exactly(17)) + mockServletContext.expects(exactly(18)) .method("getInitParameter") .will(returnValue(null)); mockServletContext.expects(once()) @@ -231,7 +235,7 @@ mockServletContext.expects(once()) .method("getInitParameterNames") .will(returnValue(Collections.enumeration(names))); - mockServletContext.expects(exactly(17)) + mockServletContext.expects(exactly(18)) .method("getInitParameter") .will(returnValue(null)); mockServletContext.expects(once())
Modified: trunk/core/src/test/java/org/codehaus/waffle/servlet/WaffleServletTest.java (130 => 131)
--- trunk/core/src/test/java/org/codehaus/waffle/servlet/WaffleServletTest.java 2007-06-02 04:16:01 UTC (rev 130) +++ trunk/core/src/test/java/org/codehaus/waffle/servlet/WaffleServletTest.java 2007-06-02 05:18:11 UTC (rev 131) @@ -10,25 +10,26 @@ *****************************************************************************/ package org.codehaus.waffle.servlet; +import ognl.DefaultTypeConverter; import org.codehaus.waffle.Constants; import org.codehaus.waffle.WaffleComponentRegistry; import org.codehaus.waffle.WaffleException; -import org.codehaus.waffle.controller.ControllerDefinition; -import org.codehaus.waffle.controller.ControllerDefinitionFactory; import org.codehaus.waffle.action.ActionMethodExecutor; import org.codehaus.waffle.action.ActionMethodResponse; import org.codehaus.waffle.action.ActionMethodResponseHandler; +import org.codehaus.waffle.action.InterceptingActionMethodExecutor; import org.codehaus.waffle.action.MethodDefinition; -import org.codehaus.waffle.action.InterceptingActionMethodExecutor; import org.codehaus.waffle.action.MethodInvocationException; import org.codehaus.waffle.bind.OgnlDataBinder; +import org.codehaus.waffle.bind.RequestAttributeBinder; import org.codehaus.waffle.context.RequestLevelContainer; import org.codehaus.waffle.context.pico.PicoContextContainer; +import org.codehaus.waffle.controller.ControllerDefinition; +import org.codehaus.waffle.controller.ControllerDefinitionFactory; import org.codehaus.waffle.testmodel.StubWaffleComponentRegistry; import org.codehaus.waffle.validation.ErrorsContext; import org.codehaus.waffle.validation.Validator; import org.codehaus.waffle.view.View; -import ognl.DefaultTypeConverter; import org.jmock.Mock; import org.jmock.MockObjectTestCase; import org.picocontainer.defaults.DefaultPicoContainer; @@ -102,7 +103,6 @@ .with(eq("org.codehaus.waffle.WaffleComponentRegistry")) .will(returnValue(null)); - // Mock ServletConfig Mock mockServletConfig = mock(ServletConfig.class); @@ -117,7 +117,7 @@ mockServletConfig.expects(once()) .method("getInitParameter") .with(eq(Constants.METHOD_INVOCATION_ERROR_PAGE)) - .will(returnValue("foo.html")); + .will(returnValue("foo.html")); final ServletConfig servletConfig = (ServletConfig) mockServletConfig.proxy(); WaffleServlet servlet = new WaffleServlet() { @@ -185,6 +185,13 @@ .with(isA(ControllerDefinition.class), isA(ErrorsContext.class)); Validator validator = (Validator) mockValidator.proxy(); + // Mock RequestAttributeBinder + Mock mockRequestAttributeBinder = mock(RequestAttributeBinder.class); + mockRequestAttributeBinder.expects(once()) + .method("bind") + .with(same(request), isA(NonDispatchingController.class)); + RequestAttributeBinder requestAttributeBinder = (RequestAttributeBinder) mockRequestAttributeBinder.proxy(); + // Set up what normally would happen via "init()" Field dataBinderField = WaffleServlet.class.getDeclaredField("dataBinder"); dataBinderField.setAccessible(true); @@ -198,6 +205,9 @@ Field validatorFactoryField = WaffleServlet.class.getDeclaredField("validator"); validatorFactoryField.setAccessible(true); validatorFactoryField.set(waffleServlet, validator); + Field requestAttributeBinderField = WaffleServlet.class.getDeclaredField("requestAttributeBinder"); + requestAttributeBinderField.setAccessible(true); + requestAttributeBinderField.set(waffleServlet, requestAttributeBinder); waffleServlet.service(request, response); assertEquals(1, nonDispatchingController.getCount()); @@ -253,19 +263,6 @@ Mock mockResponse = mock(HttpServletResponse.class); HttpServletResponse response = (HttpServletResponse) mockResponse.proxy(); - // stub out what we don't want called ... execute it - WaffleServlet waffleServlet = new WaffleServlet() { - @Override - protected ControllerDefinition getControllerDefinition(HttpServletRequest request, HttpServletResponse response) { - return new ControllerDefinition("no name", nonDispatchingController, null); - } - - @Override - public void log(String string) { - // ignore - } - }; - // Mock ActionMethodResponseHandler Mock mockActionMethodResponseHandler = mock(ActionMethodResponseHandler.class); mockActionMethodResponseHandler.expects(once()) @@ -281,19 +278,31 @@ .with(isA(ControllerDefinition.class), isA(ErrorsContext.class)); Validator validator = (Validator) mockValidator.proxy(); - // Set up what normally would happen via "init()" - Field dataBinderField = WaffleServlet.class.getDeclaredField("dataBinder"); - dataBinderField.setAccessible(true); - dataBinderField.set(waffleServlet, new OgnlDataBinder(new DefaultTypeConverter(), null)); + // Mock + Mock mockRequestAttributeBinder = mock(RequestAttributeBinder.class); + mockRequestAttributeBinder.expects(once()) + .method("bind") + .with(same(request), same(nonDispatchingController)); + RequestAttributeBinder requestAttributeBinder = (RequestAttributeBinder) mockRequestAttributeBinder.proxy(); + + // stub out what we don't want called ... execute it + WaffleServlet waffleServlet = new WaffleServlet(null, + new OgnlDataBinder(new DefaultTypeConverter(), null), + null, + actionMethodResponseHandler, + validator, + requestAttributeBinder) { + @Override + protected ControllerDefinition getControllerDefinition(HttpServletRequest request, HttpServletResponse response) { + return new ControllerDefinition("no name", nonDispatchingController, null); + } - Field methodResponseHandlerField = WaffleServlet.class.getDeclaredField("actionMethodResponseHandler"); - methodResponseHandlerField.setAccessible(true); - methodResponseHandlerField.set(waffleServlet, actionMethodResponseHandler); + @Override + public void log(String string) { + // ignore + } + }; - Field validatorFactoryField = WaffleServlet.class.getDeclaredField("validator"); - validatorFactoryField.setAccessible(true); - validatorFactoryField.set(waffleServlet, validator); - waffleServlet.service(request, response); }
Added: trunk/core/src/test/java/org/codehaus/waffle/testmodel/StubRequestAttributeBinder.java (0 => 131)
--- trunk/core/src/test/java/org/codehaus/waffle/testmodel/StubRequestAttributeBinder.java (rev 0) +++ trunk/core/src/test/java/org/codehaus/waffle/testmodel/StubRequestAttributeBinder.java 2007-06-02 05:18:11 UTC (rev 131) @@ -0,0 +1,10 @@ +package org.codehaus.waffle.testmodel; + +import org.codehaus.waffle.bind.RequestAttributeBinder; + +import javax.servlet.http.HttpServletRequest; + +public class StubRequestAttributeBinder implements RequestAttributeBinder { + public void bind(HttpServletRequest request, Object controller) { + } +}
To unsubscribe from this list please visit:
