提交 f19f55a5 编写于 作者: J Juergen Hoeller

Removed Spring MVC command/form controller class hierarchy

上级 74021b9e
/*
* Copyright 2002-2012 the original author or authors.
*
* 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.springframework.web.portlet.mvc;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import org.springframework.validation.BindException;
import org.springframework.web.portlet.ModelAndView;
import org.springframework.web.portlet.bind.PortletRequestDataBinder;
import org.springframework.web.portlet.util.PortletUtils;
/**
* <p>Abstract base class for custom command controllers. Autopopulates a
* command bean from the request. For command validation, a validator
* (property inherited from BaseCommandController) can be used.</p>
*
* <p>This command controller should preferrable not be used to handle form
* submission, because functionality for forms is more offered in more
* detail by the {@link org.springframework.web.portlet.mvc.AbstractFormController
* AbstractFormController} and its corresponding implementations.</p>
*
* <p><b><a name="config">Exposed configuration properties</a>
* (<a href="BaseCommandController.html#config">and those defined by superclass</a>):</b><br>
* <i>none</i> (so only those available in superclass).</p>
*
* <p><b><a name="workflow">Workflow
* (<a name="BaseCommandController.html#workflow">and that defined by superclass</a>):</b><br>
*
* @author John A. Lewis
* @author Juergen Hoeller
* @since 2.0
* @see #setCommandClass
* @see #setCommandName
* @see #setValidator
* @deprecated as of Spring 3.0, in favor of annotated controllers
*/
@Deprecated
public abstract class AbstractCommandController extends BaseCommandController {
/**
* This render parameter is used to indicate forward to the render phase
* that a valid command (and errors) object is in the session.
*/
private static final String COMMAND_IN_SESSION_PARAMETER = "command-in-session";
private static final String TRUE = Boolean.TRUE.toString();
/**
* Create a new AbstractCommandController.
*/
public AbstractCommandController() {
}
/**
* Create a new AbstractCommandController.
* @param commandClass class of the command bean
*/
public AbstractCommandController(Class commandClass) {
setCommandClass(commandClass);
}
/**
* Create a new AbstractCommandController.
* @param commandClass class of the command bean
* @param commandName name of the command bean
*/
public AbstractCommandController(Class commandClass, String commandName) {
setCommandClass(commandClass);
setCommandName(commandName);
}
@Override
protected final void handleActionRequestInternal(ActionRequest request, ActionResponse response)
throws Exception {
// Create the command object.
Object command = getCommand(request);
// Compute the errors object.
PortletRequestDataBinder binder = bindAndValidate(request, command);
BindException errors = new BindException(binder.getBindingResult());
// Actually handle the action.
handleAction(request, response, command, errors);
// Pass the command and errors forward to the render phase.
setRenderCommandAndErrors(request, command, errors);
setCommandInSession(response);
}
@Override
protected final ModelAndView handleRenderRequestInternal(
RenderRequest request, RenderResponse response) throws Exception {
Object command = null;
BindException errors = null;
// Get the command and errors objects from the session, if they exist.
if (isCommandInSession(request)) {
logger.debug("Render phase obtaining command and errors objects from session");
command = getRenderCommand(request);
errors = getRenderErrors(request);
}
else {
logger.debug("Render phase creating new command and errors objects");
command = getCommand(request);
PortletRequestDataBinder binder = bindAndValidate(request, command);
errors = new BindException(binder.getBindingResult());
}
return handleRender(request, response, command, errors);
}
/**
* Template method for request handling, providing a populated and validated instance
* of the command class, and an Errors object containing binding and validation errors.
* <p>Call {@code errors.getModel()} to populate the ModelAndView model
* with the command and the Errors instance, under the specified command name,
* as expected by the "spring:bind" tag.
* @param request current action request
* @param response current action response
* @param command the populated command object
* @param errors validation errors holder
* @see org.springframework.validation.Errors
* @see org.springframework.validation.BindException#getModel
*/
protected abstract void handleAction(
ActionRequest request, ActionResponse response, Object command, BindException errors)
throws Exception;
/**
* Template method for render request handling, providing a populated and validated instance
* of the command class, and an Errors object containing binding and validation errors.
* <p>Call {@code errors.getModel()} to populate the ModelAndView model
* with the command and the Errors instance, under the specified command name,
* as expected by the "spring:bind" tag.
* @param request current render request
* @param response current render response
* @param command the populated command object
* @param errors validation errors holder
* @return a ModelAndView to render, or null if handled directly
* @see org.springframework.validation.Errors
* @see org.springframework.validation.BindException#getModel
*/
protected abstract ModelAndView handleRender(
RenderRequest request, RenderResponse response, Object command, BindException errors)
throws Exception;
/**
* Return the name of the render parameter that indicates there
* is a valid command (and errors) object in the session.
* @return the name of the render parameter
* @see javax.portlet.RenderRequest#getParameter
*/
protected String getCommandInSessionParameterName() {
return COMMAND_IN_SESSION_PARAMETER;
}
/**
* Set the action response parameter that indicates there is a
* command (and errors) object in the session for the render phase.
* @param response the current action response
* @see #getCommandInSessionParameterName
* @see #isCommandInSession
*/
protected final void setCommandInSession(ActionResponse response) {
if (logger.isDebugEnabled()) {
logger.debug("Setting render parameter [" + getCommandInSessionParameterName() +
"] to indicate a valid command (and errors) object are in the session");
}
try {
response.setRenderParameter(getCommandInSessionParameterName(), TRUE);
}
catch (IllegalStateException ex) {
// Ignore in case sendRedirect was already set.
}
}
/**
* Determine if there is a valid command (and errors) object in the
* session for this render request.
* @param request current render request
* @return if there is a valid command object in the session
* @see #getCommandInSessionParameterName
* @see #setCommandInSession
*/
protected boolean isCommandInSession(RenderRequest request) {
return (TRUE.equals(request.getParameter(getCommandInSessionParameterName())) &&
PortletUtils.getSessionAttribute(request, getRenderCommandSessionAttributeName()) != null);
}
}
......@@ -16,42 +16,29 @@
package org.springframework.web.portlet;
import java.io.IOException;
import java.util.Locale;
import java.util.Map;
import javax.portlet.PortletContext;
import javax.portlet.PortletException;
import javax.portlet.PortletMode;
import javax.portlet.PortletSecurityException;
import javax.portlet.PortletSession;
import junit.framework.TestCase;
import org.springframework.tests.sample.beans.TestBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.i18n.LocaleContext;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.mock.web.portlet.MockActionRequest;
import org.springframework.mock.web.portlet.MockActionResponse;
import org.springframework.mock.web.portlet.MockEvent;
import org.springframework.mock.web.portlet.MockEventRequest;
import org.springframework.mock.web.portlet.MockEventResponse;
import org.springframework.mock.web.portlet.MockPortletConfig;
import org.springframework.mock.web.portlet.MockPortletContext;
import org.springframework.mock.web.portlet.MockPortletSession;
import org.springframework.mock.web.portlet.MockRenderRequest;
import org.springframework.mock.web.portlet.MockRenderResponse;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.portlet.context.PortletApplicationContextUtils;
import org.springframework.web.portlet.context.PortletConfigAwareBean;
import org.springframework.web.portlet.context.PortletContextAwareBean;
import org.springframework.web.portlet.context.PortletRequestAttributes;
import org.springframework.web.portlet.handler.PortletSessionRequiredException;
import org.springframework.web.portlet.multipart.MultipartActionRequest;
import org.springframework.web.portlet.multipart.PortletMultipartResolver;
import org.springframework.web.servlet.ViewRendererServlet;
......@@ -64,25 +51,16 @@ import org.springframework.web.servlet.view.InternalResourceView;
*/
public class DispatcherPortletTests extends TestCase {
private MockPortletConfig simplePortletConfig;
private MockPortletConfig complexPortletConfig;
private DispatcherPortlet simpleDispatcherPortlet;
private DispatcherPortlet complexDispatcherPortlet;
@Override
protected void setUp() throws PortletException {
simplePortletConfig = new MockPortletConfig(new MockPortletContext(), "simple");
complexPortletConfig = new MockPortletConfig(simplePortletConfig.getPortletContext(), "complex");
complexPortletConfig = new MockPortletConfig(new MockPortletContext(), "complex");
complexPortletConfig.addInitParameter("publishContext", "false");
simpleDispatcherPortlet = new DispatcherPortlet();
simpleDispatcherPortlet.setContextClass(SimplePortletApplicationContext.class);
simpleDispatcherPortlet.init(simplePortletConfig);
complexDispatcherPortlet = new DispatcherPortlet();
complexDispatcherPortlet.setContextClass(ComplexPortletApplicationContext.class);
complexDispatcherPortlet.setNamespace("test");
......@@ -103,14 +81,6 @@ public class DispatcherPortletTests extends TestCase {
}
public void testDispatcherPortlets() {
assertTrue("Correct namespace",
("simple" + FrameworkPortlet.DEFAULT_NAMESPACE_SUFFIX).equals(simpleDispatcherPortlet.getNamespace()));
assertTrue("Correct attribute",
(FrameworkPortlet.PORTLET_CONTEXT_PREFIX + "simple").equals(simpleDispatcherPortlet.getPortletContextAttributeName()));
assertTrue("Context published",
simpleDispatcherPortlet.getPortletApplicationContext() ==
getPortletContext().getAttribute(FrameworkPortlet.PORTLET_CONTEXT_PREFIX + "simple"));
assertTrue("Correct namespace", "test".equals(complexDispatcherPortlet.getNamespace()));
assertTrue("Correct attribute",
(FrameworkPortlet.PORTLET_CONTEXT_PREFIX + "complex").equals(complexDispatcherPortlet.getPortletContextAttributeName()));
......@@ -118,192 +88,6 @@ public class DispatcherPortletTests extends TestCase {
getPortletContext().getAttribute(FrameworkPortlet.PORTLET_CONTEXT_PREFIX + "complex") == null);
}
public void testSimpleValidActionRequest() throws Exception {
MockActionRequest request = new MockActionRequest();
MockActionResponse response = new MockActionResponse();
request.setParameter("action", "form");
request.setParameter("age", "29");
simpleDispatcherPortlet.processAction(request, response);
String exceptionParam = response.getRenderParameter(DispatcherPortlet.ACTION_EXCEPTION_RENDER_PARAMETER);
assertNull(exceptionParam);
SimplePortletApplicationContext ac = (SimplePortletApplicationContext)simpleDispatcherPortlet.getPortletApplicationContext();
String commandAttribute = ac.getRenderCommandSessionAttributeName();
TestBean testBean = (TestBean) request.getPortletSession().getAttribute(commandAttribute);
assertEquals(39, testBean.getAge());
}
public void testSimpleInvalidActionRequest() throws Exception {
MockActionRequest request = new MockActionRequest();
MockActionResponse response = new MockActionResponse();
request.setParameter("action", "invalid");
simpleDispatcherPortlet.processAction(request, response);
String exceptionParam = response.getRenderParameter(DispatcherPortlet.ACTION_EXCEPTION_RENDER_PARAMETER);
assertNotNull(exceptionParam);
assertTrue(exceptionParam.startsWith(NoHandlerFoundException.class.getName()));
}
public void testSimpleInvalidActionRequestWithoutHandling() throws Exception {
MockActionRequest request = new MockActionRequest();
MockActionResponse response = new MockActionResponse();
request.setParameter("action", "invalid");
simpleDispatcherPortlet.setForwardActionException(false);
try {
simpleDispatcherPortlet.processAction(request, response);
fail("Should have thrown a " + NoHandlerFoundException.class);
}
catch (NoHandlerFoundException ex) {
// expected
}
}
public void testSimpleValidEventRequest() throws Exception {
MockEvent event = new MockEvent("test-event");
MockEventRequest request = new MockEventRequest(event);
MockEventResponse response = new MockEventResponse();
request.setParameter("action", "form");
simpleDispatcherPortlet.processEvent(request, response);
assertEquals("test-event", response.getRenderParameter("event"));
}
public void testSimpleInvalidEventRequest() throws Exception {
MockEvent event = new MockEvent("test-event");
MockEventRequest request = new MockEventRequest(event);
MockEventResponse response = new MockEventResponse();
request.setParameter("action", "invalid");
try {
simpleDispatcherPortlet.processEvent(request, response);
fail("Should have thrown a " + NoHandlerFoundException.class);
}
catch (NoHandlerFoundException ex) {
// expected
}
}
public void testSimpleInvalidEventRequestWithHandling() throws Exception {
MockEvent event = new MockEvent("event");
MockEventRequest request = new MockEventRequest(event);
MockEventResponse response = new MockEventResponse();
request.setParameter("action", "invalid");
simpleDispatcherPortlet.setForwardEventException(true);
simpleDispatcherPortlet.processEvent(request, response);
String exceptionParam = response.getRenderParameter(DispatcherPortlet.ACTION_EXCEPTION_RENDER_PARAMETER);
assertNotNull(exceptionParam);
assertTrue(exceptionParam.startsWith(NoHandlerFoundException.class.getName()));
}
public void testSimpleFormViewNoBindOnNewForm() throws Exception {
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
request.setParameter("action", "form");
request.setParameter("age", "29");
simpleDispatcherPortlet.doDispatch(request, response);
assertEquals("5", response.getContentAsString());
}
public void testSimpleFormViewBindOnNewForm() throws Exception {
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
request.setParameter("action", "form-bind");
request.setParameter("age", "29");
simpleDispatcherPortlet.doDispatch(request, response);
assertEquals("34", response.getContentAsString());
}
public void testSimpleFormViewWithSessionAndBindOnNewForm() throws Exception {
MockRenderRequest renderRequest = new MockRenderRequest();
MockRenderResponse renderResponse = new MockRenderResponse();
renderRequest.setParameter("action", "form-session-bind");
renderRequest.setParameter("age", "30");
TestBean testBean = new TestBean();
testBean.setAge(40);
SimplePortletApplicationContext ac =
(SimplePortletApplicationContext)simpleDispatcherPortlet.getPortletApplicationContext();
String formAttribute = ac.getFormSessionAttributeName();
PortletSession session = new MockPortletSession();
session.setAttribute(formAttribute, testBean);
renderRequest.setSession(session);
simpleDispatcherPortlet.doDispatch(renderRequest, renderResponse);
assertEquals("35", renderResponse.getContentAsString());
}
public void testSimpleFormViewWithSessionNoBindOnNewForm() throws Exception {
MockActionRequest actionRequest = new MockActionRequest();
MockActionResponse actionResponse = new MockActionResponse();
actionRequest.setSession(new MockPortletSession());
actionRequest.setParameter("action", "form-session-nobind");
actionRequest.setParameter("age", "27");
simpleDispatcherPortlet.processAction(actionRequest, actionResponse);
Map renderParameters = actionResponse.getRenderParameterMap();
MockRenderRequest renderRequest = new MockRenderRequest();
MockRenderResponse renderResponse = new MockRenderResponse();
renderRequest.setParameters(renderParameters);
renderRequest.setParameter("action", "form-session-nobind");
renderRequest.setParameter("age", "30");
renderRequest.setSession(actionRequest.getPortletSession());
simpleDispatcherPortlet.doDispatch(renderRequest, renderResponse);
assertEquals("finished42", renderResponse.getContentAsString());
}
public void testSimpleRequiredSessionFormWithoutSession() throws Exception {
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
request.setParameter("action", "form-session-bind");
try {
simpleDispatcherPortlet.doDispatch(request, response);
fail("Should have thrown PortletSessionRequiredException");
}
catch (PortletSessionRequiredException ex) {
// expected
}
}
public void testSimpleFormSubmission() throws Exception {
MockActionRequest actionRequest = new MockActionRequest();
MockActionResponse actionResponse = new MockActionResponse();
actionRequest.setParameter("action", "form");
actionRequest.setParameter("age", "29");
simpleDispatcherPortlet.processAction(actionRequest, actionResponse);
MockRenderRequest renderRequest = new MockRenderRequest();
MockRenderResponse renderResponse = new MockRenderResponse();
renderRequest.setSession(actionRequest.getPortletSession());
renderRequest.setParameters(actionResponse.getRenderParameterMap());
renderRequest.setParameter("action", "form");
simpleDispatcherPortlet.doDispatch(renderRequest, renderResponse);
assertEquals("finished44", renderResponse.getContentAsString());
}
public void testSimpleFormSubmissionWithValidationError() throws Exception {
MockActionRequest actionRequest = new MockActionRequest();
MockActionResponse actionResponse = new MockActionResponse();
actionRequest.setParameter("action", "form");
actionRequest.setParameter("age", "XX");
simpleDispatcherPortlet.processAction(actionRequest, actionResponse);
MockRenderRequest renderRequest = new MockRenderRequest();
MockRenderResponse renderResponse = new MockRenderResponse();
renderRequest.setSession(actionRequest.getPortletSession());
renderRequest.setParameters(actionResponse.getRenderParameterMap());
renderRequest.setParameter("action", "form");
simpleDispatcherPortlet.doDispatch(renderRequest, renderResponse);
assertEquals("5", renderResponse.getContentAsString());
}
public void testSimpleInvalidRenderRequest() throws Exception {
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
request.setParameter("action", "invalid");
try {
simpleDispatcherPortlet.doDispatch(request, response);
fail("Should have thrown UnavailableException");
}
catch (NoHandlerFoundException ex) {
// expected
}
}
public void testPortletModeParameterMappingHelp1() throws Exception {
MockActionRequest request = new MockActionRequest();
MockActionResponse response = new MockActionResponse();
......@@ -859,115 +643,6 @@ public class DispatcherPortletTests extends TestCase {
}
}
public void testValidActionRequestWithExistingThreadLocalRequestContext() throws IOException, PortletException {
MockActionRequest request = new MockActionRequest();
MockActionResponse response = new MockActionResponse();
request.addPreferredLocale(Locale.GERMAN);
request.setParameter("action", "form");
request.setParameter("age", "29");
// see RequestContextListener.requestInitialized()
try {
LocaleContextHolder.setLocale(request.getLocale());
RequestContextHolder.setRequestAttributes(new PortletRequestAttributes(request));
LocaleContext servletLocaleContext = LocaleContextHolder.getLocaleContext();
RequestAttributes servletRequestAttrs = RequestContextHolder.getRequestAttributes();
simpleDispatcherPortlet.processAction(request, response);
assertSame(servletLocaleContext, LocaleContextHolder.getLocaleContext());
assertSame(servletRequestAttrs, RequestContextHolder.getRequestAttributes());
}
finally {
RequestContextHolder.resetRequestAttributes();
LocaleContextHolder.resetLocaleContext();
}
}
public void testValidRenderRequestWithExistingThreadLocalRequestContext() throws IOException, PortletException {
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
request.addPreferredLocale(Locale.GERMAN);
// see RequestContextListener.requestInitialized()
try {
LocaleContextHolder.setLocale(request.getLocale());
RequestContextHolder.setRequestAttributes(new PortletRequestAttributes(request));
LocaleContext servletLocaleContext = LocaleContextHolder.getLocaleContext();
RequestAttributes servletRequestAttrs = RequestContextHolder.getRequestAttributes();
request.setParameter("action", "form");
request.setParameter("age", "29");
simpleDispatcherPortlet.doDispatch(request, response);
assertSame(servletLocaleContext, LocaleContextHolder.getLocaleContext());
assertSame(servletRequestAttrs, RequestContextHolder.getRequestAttributes());
}
finally {
RequestContextHolder.resetRequestAttributes();
LocaleContextHolder.resetLocaleContext();
}
}
public void testInvalidActionRequestWithExistingThreadLocalRequestContext() throws IOException, PortletException {
MockActionRequest request = new MockActionRequest();
MockActionResponse response = new MockActionResponse();
request.addPreferredLocale(Locale.GERMAN);
// see RequestContextListener.requestInitialized()
try {
LocaleContextHolder.setLocale(request.getLocale());
RequestContextHolder.setRequestAttributes(new PortletRequestAttributes(request));
LocaleContext servletLocaleContext = LocaleContextHolder.getLocaleContext();
RequestAttributes servletRequestAttrs = RequestContextHolder.getRequestAttributes();
request.setParameter("action", "invalid");
simpleDispatcherPortlet.processAction(request, response);
String exceptionParam = response.getRenderParameter(DispatcherPortlet.ACTION_EXCEPTION_RENDER_PARAMETER);
assertNotNull(exceptionParam); // ensure that an exceptional condition occured
assertSame(servletLocaleContext, LocaleContextHolder.getLocaleContext());
assertSame(servletRequestAttrs, RequestContextHolder.getRequestAttributes());
}
finally {
RequestContextHolder.resetRequestAttributes();
LocaleContextHolder.resetLocaleContext();
}
}
public void testInvalidRenderRequestWithExistingThreadLocalRequestContext() throws IOException, PortletException {
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
request.addPreferredLocale(Locale.GERMAN);
// see RequestContextListener.requestInitialized()
try {
LocaleContextHolder.setLocale(request.getLocale());
RequestContextHolder.setRequestAttributes(new PortletRequestAttributes(request));
LocaleContext servletLocaleContext = LocaleContextHolder.getLocaleContext();
RequestAttributes servletRequestAttrs = RequestContextHolder.getRequestAttributes();
try {
simpleDispatcherPortlet.doDispatch(request, response);
fail("should have failed to find a handler and raised an NoHandlerFoundExceptionException");
}
catch (NoHandlerFoundException ex) {
// expected
}
assertSame(servletLocaleContext, LocaleContextHolder.getLocaleContext());
assertSame(servletRequestAttrs, RequestContextHolder.getRequestAttributes());
}
finally {
RequestContextHolder.resetRequestAttributes();
LocaleContextHolder.resetLocaleContext();
}
}
public void testDispatcherPortletRefresh() throws PortletException {
MockPortletContext portletContext = new MockPortletContext("org/springframework/web/portlet/context");
DispatcherPortlet portlet = new DispatcherPortlet();
......
/*
* Copyright 2002-2013 the original author or authors.
*
* 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.springframework.web.portlet;
import java.io.IOException;
import java.util.Map;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.tests.sample.beans.TestBean;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.validation.BindException;
import org.springframework.web.portlet.context.StaticPortletApplicationContext;
import org.springframework.web.portlet.handler.ParameterHandlerMapping;
import org.springframework.web.portlet.mvc.EventAwareController;
import org.springframework.web.portlet.mvc.SimpleFormController;
/**
* @author Mark Fisher
*/
public class SimplePortletApplicationContext extends StaticPortletApplicationContext {
private String renderCommandSessionAttributeName;
private String formSessionAttributeName;
@Override
public void refresh() throws BeansException {
MutablePropertyValues pvs = new MutablePropertyValues();
registerSingleton("controller1", TestFormController.class, pvs);
pvs = new MutablePropertyValues();
pvs.add("bindOnNewForm", "true");
registerSingleton("controller2", TestFormController.class, pvs);
pvs = new MutablePropertyValues();
pvs.add("requireSession", "true");
pvs.add("sessionForm", "true");
pvs.add("bindOnNewForm", "true");
registerSingleton("controller3", TestFormController.class, pvs);
pvs = new MutablePropertyValues();
pvs.add("requireSession", "true");
pvs.add("sessionForm", "true");
pvs.add("bindOnNewForm", "false");
registerSingleton("controller4", TestFormController.class, pvs);
pvs = new MutablePropertyValues();
Map parameterMap = new ManagedMap();
parameterMap.put("form", new RuntimeBeanReference("controller1"));
parameterMap.put("form-bind", new RuntimeBeanReference("controller2"));
parameterMap.put("form-session-bind", new RuntimeBeanReference("controller3"));
parameterMap.put("form-session-nobind", new RuntimeBeanReference("controller4"));
pvs.addPropertyValue(new PropertyValue("parameterMap", parameterMap));
registerSingleton("handlerMapping", ParameterHandlerMapping.class, pvs);
super.refresh();
TestFormController controller1 = (TestFormController) getBean("controller1");
this.renderCommandSessionAttributeName = controller1.getRenderCommandName();
this.formSessionAttributeName = controller1.getFormSessionName();
}
public String getRenderCommandSessionAttributeName() {
return this.renderCommandSessionAttributeName;
}
public String getFormSessionAttributeName() {
return this.formSessionAttributeName;
}
public static class TestFormController extends SimpleFormController implements EventAwareController {
TestFormController() {
super();
this.setCommandClass(TestBean.class);
this.setCommandName("testBean");
this.setFormView("form");
}
@Override
public void doSubmitAction(Object command) {
TestBean testBean = (TestBean) command;
testBean.setAge(testBean.getAge() + 10);
}
@Override
public ModelAndView showForm(RenderRequest request, RenderResponse response, BindException errors) throws Exception {
TestBean testBean = (TestBean) errors.getModel().get(getCommandName());
this.writeResponse(response, testBean, false);
return null;
}
@Override
public ModelAndView onSubmitRender(RenderRequest request, RenderResponse response, Object command, BindException errors)
throws IOException {
TestBean testBean = (TestBean) command;
this.writeResponse(response, testBean, true);
return null;
}
private String getRenderCommandName() {
return this.getRenderCommandSessionAttributeName();
}
private String getFormSessionName() {
return this.getFormSessionAttributeName();
}
private void writeResponse(RenderResponse response, TestBean testBean, boolean finished) throws IOException {
response.getWriter().write((finished ? "finished" : "") + (testBean.getAge() + 5));
}
@Override
public void handleEventRequest(EventRequest request, EventResponse response) throws Exception {
response.setRenderParameter("event", request.getEvent().getName());
}
}
}
/*
* Copyright 2002-2013 the original author or authors.
*
* 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.springframework.web.portlet.mvc;
import java.beans.PropertyEditorSupport;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletRequest;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.WindowState;
import junit.framework.TestCase;
import org.springframework.tests.sample.beans.ITestBean;
import org.springframework.tests.sample.beans.TestBean;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.mock.web.portlet.MockActionRequest;
import org.springframework.mock.web.portlet.MockActionResponse;
import org.springframework.mock.web.portlet.MockRenderRequest;
import org.springframework.mock.web.portlet.MockRenderResponse;
import org.springframework.validation.BindException;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
import org.springframework.web.portlet.ModelAndView;
import org.springframework.web.portlet.bind.PortletRequestDataBinder;
import org.springframework.web.portlet.handler.PortletSessionRequiredException;
/**
* @author Mark Fisher
*/
@Deprecated
public class CommandControllerTests extends TestCase {
private static final String ERRORS_KEY = "errors";
public void testRenderRequestWithNoParams() throws Exception {
TestController tc = new TestController();
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
request.setContextPath("test");
ModelAndView mav = tc.handleRenderRequest(request, response);
assertEquals("test-view", mav.getViewName());
assertNotNull(mav.getModel().get(tc.getCommandName()));
BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
assertNotNull(errors);
assertEquals("There should be no errors", 0, errors.getErrorCount());
}
public void testRenderRequestWithParams() throws Exception {
TestController tc = new TestController();
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
String name = "test";
int age = 30;
request.addParameter("name", name);
request.addParameter("age", "" + age);
request.setContextPath("test");
ModelAndView mav = tc.handleRenderRequest(request, response);
assertEquals("test-view", mav.getViewName());
TestBean command = (TestBean)mav.getModel().get(tc.getCommandName());
assertEquals("Name should be bound", name, command.getName());
assertEquals("Age should be bound", age, command.getAge());
BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
assertNotNull(errors);
assertEquals("There should be no errors", 0, errors.getErrorCount());
}
public void testRenderRequestWithMismatch() throws Exception {
TestController tc = new TestController();
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
String name = "test";
request.addParameter("name", name);
request.addParameter("age", "zzz");
request.setContextPath("test");
ModelAndView mav = tc.handleRenderRequest(request, response);
assertEquals("test-view", mav.getViewName());
TestBean command = (TestBean)mav.getModel().get(tc.getCommandName());
assertNotNull(command);
assertEquals("Name should be bound", name, command.getName());
BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
assertEquals("There should be 1 error", 1, errors.getErrorCount());
assertNotNull(errors.getFieldError("age"));
assertEquals("typeMismatch", errors.getFieldError("age").getCode());
}
public void testRenderWhenMinimizedReturnsNull() throws Exception {
TestController tc = new TestController();
assertFalse(tc.isRenderWhenMinimized());
MockRenderRequest request = new MockRenderRequest();
request.setWindowState(WindowState.MINIMIZED);
MockRenderResponse response = new MockRenderResponse();
ModelAndView mav = tc.handleRenderRequest(request, response);
assertNull("ModelAndView should be null", mav);
}
public void testAllowRenderWhenMinimized() throws Exception {
TestController tc = new TestController();
tc.setRenderWhenMinimized(true);
MockRenderRequest request = new MockRenderRequest();
request.setWindowState(WindowState.MINIMIZED);
request.setContextPath("test");
MockRenderResponse response = new MockRenderResponse();
ModelAndView mav = tc.handleRenderRequest(request, response);
assertNotNull("ModelAndView should not be null", mav);
assertEquals("test-view", mav.getViewName());
assertNotNull(mav.getModel().get(tc.getCommandName()));
BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
assertEquals("There should be no errors", 0, errors.getErrorCount());
}
public void testRequiresSessionWithoutSession() throws Exception {
TestController tc = new TestController();
tc.setRequireSession(true);
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
try {
tc.handleRenderRequest(request, response);
fail("Should have thrown PortletSessionRequiredException");
}
catch (PortletSessionRequiredException ex) {
// expected
}
}
public void testRequiresSessionWithSession() throws Exception {
TestController tc = new TestController();
tc.setRequireSession(true);
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
// create the session
request.getPortletSession(true);
try {
tc.handleRenderRequest(request, response);
}
catch (PortletSessionRequiredException ex) {
fail("Should not have thrown PortletSessionRequiredException");
}
}
public void testRenderRequestWithoutCacheSetting() throws Exception {
TestController tc = new TestController();
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
tc.handleRenderRequest(request, response);
String cacheProperty = response.getProperty(RenderResponse.EXPIRATION_CACHE);
assertNull("Expiration-cache should be null", cacheProperty);
}
public void testRenderRequestWithNegativeCacheSetting() throws Exception {
TestController tc = new TestController();
tc.setCacheSeconds(-99);
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
tc.handleRenderRequest(request, response);
String cacheProperty = response.getProperty(RenderResponse.EXPIRATION_CACHE);
assertNull("Expiration-cache should be null", cacheProperty);
}
public void testRenderRequestWithZeroCacheSetting() throws Exception {
TestController tc = new TestController();
tc.setCacheSeconds(0);
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
tc.handleRenderRequest(request, response);
String cacheProperty = response.getProperty(RenderResponse.EXPIRATION_CACHE);
assertEquals("Expiration-cache should be set to 0 seconds", "0", cacheProperty);
}
public void testRenderRequestWithPositiveCacheSetting() throws Exception {
TestController tc = new TestController();
tc.setCacheSeconds(30);
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
tc.handleRenderRequest(request, response);
String cacheProperty = response.getProperty(RenderResponse.EXPIRATION_CACHE);
assertEquals("Expiration-cache should be set to 30 seconds", "30", cacheProperty);
}
public void testActionRequest() throws Exception {
TestController tc = new TestController();
MockActionRequest request = new MockActionRequest();
MockActionResponse response = new MockActionResponse();
tc.handleActionRequest(request, response);
TestBean command = (TestBean)request.getPortletSession().getAttribute(tc.getRenderCommandSessionAttributeName());
assertTrue(command.isJedi());
}
public void testSuppressBinding() throws Exception {
TestController tc = new TestController() {
@Override
protected boolean suppressBinding(PortletRequest request) {
return true;
}
};
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
String name = "test";
int age = 30;
request.addParameter("name", name);
request.addParameter("age", "" + age);
request.setContextPath("test");
ModelAndView mav = tc.handleRenderRequest(request, response);
assertEquals("test-view", mav.getViewName());
TestBean command = (TestBean)mav.getModel().get(tc.getCommandName());
assertNotNull(command);
assertTrue("Name should not have been bound", name != command.getName());
assertTrue("Age should not have been bound", age != command.getAge());
BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
assertEquals("There should be no errors", 0, errors.getErrorCount());
}
public void testWithCustomDateEditor() throws Exception {
final DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
TestController tc = new TestController() {
@Override
protected void initBinder(PortletRequest request, PortletRequestDataBinder binder) {
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}
};
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
String name = "test";
int age = 30;
request.addParameter("name", name);
request.addParameter("age", "" + age);
String dateString = "07-03-2006";
Date expectedDate = dateFormat.parse(dateString);
request.addParameter("date", dateString);
ModelAndView mav = tc.handleRenderRequest(request, response);
TestBean command = (TestBean)mav.getModel().get(tc.getCommandName());
assertEquals(name, command.getName());
assertEquals(age, command.getAge());
assertEquals(expectedDate, command.getDate());
BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
assertEquals("There should be no errors", 0, errors.getErrorCount());
}
public void testWithCustomDateEditorEmptyNotAllowed() throws Exception {
final DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
TestController tc = new TestController() {
@Override
protected void initBinder(PortletRequest request, PortletRequestDataBinder binder) {
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}
};
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
String name = "test";
int age = 30;
request.addParameter("name", name);
request.addParameter("age", "" + age);
String emptyString = "";
request.addParameter("date", emptyString);
ModelAndView mav = tc.handleRenderRequest(request, response);
TestBean command = (TestBean)mav.getModel().get(tc.getCommandName());
assertEquals(name, command.getName());
assertEquals(age, command.getAge());
BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
assertEquals("There should be 1 error", 1, errors.getErrorCount());
assertNotNull(errors.getFieldError("date"));
assertEquals("typeMismatch", errors.getFieldError("date").getCode());
assertEquals(emptyString, errors.getFieldError("date").getRejectedValue());
}
public void testWithCustomDateEditorEmptyAllowed() throws Exception {
final DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
TestController tc = new TestController() {
@Override
protected void initBinder(PortletRequest request, PortletRequestDataBinder binder) {
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
};
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
String name = "test";
int age = 30;
request.addParameter("name", name);
request.addParameter("age", "" + age);
String dateString = "";
request.addParameter("date", dateString);
ModelAndView mav = tc.handleRenderRequest(request, response);
TestBean command = (TestBean)mav.getModel().get(tc.getCommandName());
assertEquals(name, command.getName());
assertEquals(age, command.getAge());
BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
assertEquals("There should be 0 errors", 0, errors.getErrorCount());
assertNull("date should be null", command.getDate());
}
public void testNestedBindingWithPropertyEditor() throws Exception {
TestController tc = new TestController() {
@Override
protected void initBinder(PortletRequest request, PortletRequestDataBinder binder) {
binder.registerCustomEditor(ITestBean.class, new PropertyEditorSupport() {
@Override
public void setAsText(String text) throws IllegalArgumentException {
setValue(new TestBean(text));
}
});
}
};
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
String name = "test";
String spouseName = "testSpouse";
int age = 30;
int spouseAge = 31;
request.addParameter("name", name);
request.addParameter("age", "" + age);
request.addParameter("spouse", spouseName);
request.addParameter("spouse.age", "" + spouseAge);
ModelAndView mav = tc.handleRenderRequest(request, response);
TestBean command = (TestBean)mav.getModel().get(tc.getCommandName());
assertEquals(name, command.getName());
assertEquals(age, command.getAge());
assertNotNull(command.getSpouse());
assertEquals(spouseName, command.getSpouse().getName());
assertEquals(spouseAge, command.getSpouse().getAge());
BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
assertEquals("There should be no errors", 0, errors.getErrorCount());
}
public void testWithValidatorNotSupportingCommandClass() throws Exception {
Validator v = new Validator() {
@Override
public boolean supports(Class c) {
return false;
}
@Override
public void validate(Object o, Errors e) {}
};
TestController tc = new TestController();
tc.setValidator(v);
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
try {
tc.handleRenderRequest(request, response);
fail("Should have thrown IllegalArgumentException");
}
catch(IllegalArgumentException e) {
// expected
}
}
public void testWithValidatorAddingGlobalError() throws Exception {
final String errorCode = "someCode";
final String defaultMessage = "validation error!";
TestController tc = new TestController();
tc.setValidator(new Validator() {
@Override
public boolean supports(Class c) {
return TestBean.class.isAssignableFrom(c);
}
@Override
public void validate(Object o, Errors e) {
e.reject(errorCode, defaultMessage);
}
});
MockRenderRequest request = new MockRenderRequest();
MockRenderResponse response = new MockRenderResponse();
ModelAndView mav = tc.handleRenderRequest(request, response);
BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
assertEquals("There should be 1 error", 1, errors.getErrorCount());
ObjectError error = errors.getGlobalError();
assertEquals(error.getCode(), errorCode);
assertEquals(error.getDefaultMessage(), defaultMessage);
}
public void testWithValidatorAndNullFieldError() throws Exception {
final String errorCode = "someCode";
final String defaultMessage = "validation error!";
TestController tc = new TestController();
tc.setValidator(new Validator() {
@Override
public boolean supports(Class c) {
return TestBean.class.isAssignableFrom(c);
}
@Override
public void validate(Object o, Errors e) {
ValidationUtils.rejectIfEmpty(e, "name", errorCode, defaultMessage);
}
});
MockRenderRequest request = new MockRenderRequest();
int age = 32;
request.setParameter("age", "" + age);
MockRenderResponse response = new MockRenderResponse();
ModelAndView mav = tc.handleRenderRequest(request, response);
TestBean command = (TestBean)mav.getModel().get(tc.getCommandName());
assertNull("name should be null", command.getName());
assertEquals(age, command.getAge());
BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
assertEquals("There should be 1 error", 1, errors.getErrorCount());
FieldError error = errors.getFieldError("name");
assertEquals(error.getCode(), errorCode);
assertEquals(error.getDefaultMessage(), defaultMessage);
}
public void testWithValidatorAndWhitespaceFieldError() throws Exception {
final String errorCode = "someCode";
final String defaultMessage = "validation error!";
TestController tc = new TestController();
tc.setValidator(new Validator() {
@Override
public boolean supports(Class c) {
return TestBean.class.isAssignableFrom(c);
}
@Override
public void validate(Object o, Errors e) {
ValidationUtils.rejectIfEmptyOrWhitespace(e, "name", errorCode, defaultMessage);
}
});
MockRenderRequest request = new MockRenderRequest();
int age = 32;
String whitespace = " \t ";
request.setParameter("age", "" + age);
request.setParameter("name", whitespace);
MockRenderResponse response = new MockRenderResponse();
ModelAndView mav = tc.handleRenderRequest(request, response);
TestBean command = (TestBean)mav.getModel().get(tc.getCommandName());
assertTrue(command.getName().equals(whitespace));
assertEquals(age, command.getAge());
BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
assertEquals("There should be 1 error", 1, errors.getErrorCount());
FieldError error = errors.getFieldError("name");
assertEquals("rejected value should contain whitespace", whitespace, error.getRejectedValue());
assertEquals(error.getCode(), errorCode);
assertEquals(error.getDefaultMessage(), defaultMessage);
}
private static class TestController extends AbstractCommandController {
private TestController() {
super(TestBean.class, "testBean");
}
@Override
protected void handleAction(ActionRequest request, ActionResponse response, Object command, BindException errors) {
((TestBean)command).setJedi(true);
}
@Override
protected ModelAndView handleRender(RenderRequest request, RenderResponse response, Object command, BindException errors) {
assertNotNull(command);
assertNotNull(errors);
Map model = new HashMap();
model.put(getCommandName(), command);
model.put(ERRORS_KEY, errors);
return new ModelAndView(request.getContextPath() + "-view", model);
}
}
}
/*
* Copyright 2002-2012 the original author or authors.
*
* 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.springframework.web.servlet.mvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.validation.BindException;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;
/**
* Abstract base class for custom command controllers.
*
* <p>Autopopulates a command bean from the request. For command validation,
* a validator (property inherited from {@link BaseCommandController}) can be
* used.
*
* <p>In most cases this command controller should not be used to handle form
* submission, because functionality for forms is offered in more detail by the
* {@link org.springframework.web.servlet.mvc.AbstractFormController} and its
* corresponding implementations.
*
* <p><b><a name="config">Exposed configuration properties</a>
* (<a href="BaseCommandController.html#config">and those defined by superclass</a>):</b><br>
* <i>none</i> (so only those available in superclass).</p>
*
* <p><b><a name="workflow">Workflow
* (<a name="BaseCommandController.html#workflow">and that defined by superclass</a>):</b><br>
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see #setCommandClass
* @see #setCommandName
* @see #setValidator
* @deprecated as of Spring 3.0, in favor of annotated controllers
*/
@Deprecated
public abstract class AbstractCommandController extends BaseCommandController {
/**
* Create a new AbstractCommandController.
*/
public AbstractCommandController() {
}
/**
* Create a new AbstractCommandController.
* @param commandClass class of the command bean
*/
public AbstractCommandController(Class commandClass) {
setCommandClass(commandClass);
}
/**
* Create a new AbstractCommandController.
* @param commandClass class of the command bean
* @param commandName name of the command bean
*/
public AbstractCommandController(Class commandClass, String commandName) {
setCommandClass(commandClass);
setCommandName(commandName);
}
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception {
Object command = getCommand(request);
ServletRequestDataBinder binder = bindAndValidate(request, command);
BindException errors = new BindException(binder.getBindingResult());
return handle(request, response, command, errors);
}
/**
* Template method for request handling, providing a populated and validated instance
* of the command class, and an Errors object containing binding and validation errors.
* <p>Call {@code errors.getModel()} to populate the ModelAndView model
* with the command and the Errors instance, under the specified command name,
* as expected by the "spring:bind" tag.
* @param request current HTTP request
* @param response current HTTP response
* @param command the populated command object
* @param errors validation errors holder
* @return a ModelAndView to render, or {@code null} if handled directly
* @see org.springframework.validation.Errors
* @see org.springframework.validation.BindException#getModel
*/
protected abstract ModelAndView handle(
HttpServletRequest request, HttpServletResponse response, Object command, BindException errors)
throws Exception;
}
/*
* Copyright 2002-2012 the original author or authors.
*
* 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.springframework.web.servlet.mvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.WebUtils;
/**
* <p>Extension of {@code SimpleFormController} that supports "cancellation"
* of form processing. By default, this controller looks for a given parameter in the
* request, identified by the {@code cancelParamKey}. If this parameter is present,
* then the controller will return the configured {@code cancelView}, otherwise
* processing is passed back to the superclass.</p>
*
* <p><b><a name="workflow">Workflow
* (<a href="SimpleFormController.html#workflow">in addition to the superclass</a>):</b><br>
* <ol>
* <li>Call to {@link #processFormSubmission processFormSubmission} which calls
* {@link #isCancelRequest} to see if the incoming request is to cancel the
* current form entry. By default, {@link #isCancelRequest} returns {@code true}
* if the configured {@code cancelParamKey} exists in the request.
* This behavior can be overridden in subclasses.</li>
* <li>If {@link #isCancelRequest} returns {@code false}, then the controller
* will delegate all processing back to {@link SimpleFormController SimpleFormController},
* otherwise it will call the {@link #onCancel} version with all parameters.
* By default, that method will delegate to the {@link #onCancel} version with just
* the command object, which will in turn simply return the configured
* {@code cancelView}. This behavior can be overridden in subclasses.</li>
* </ol>
* </p>
*
* <p>Thanks to Erwin Bolwidt for submitting the original prototype
* of such a cancellable form controller!</p>
*
* @author Rob Harrop
* @author Juergen Hoeller
* @since 1.2.3
* @see #setCancelParamKey
* @see #setCancelView
* @see #isCancelRequest(javax.servlet.http.HttpServletRequest)
* @see #onCancel(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, Object)
* @deprecated as of Spring 3.0, in favor of annotated controllers
*/
@Deprecated
public class CancellableFormController extends SimpleFormController {
/**
* Default parameter triggering the cancel action.
* Can be called even with validation errors on the form.
*/
private static final String PARAM_CANCEL = "_cancel";
private String cancelParamKey = PARAM_CANCEL;
private String cancelView;
/**
* Set the key of the request parameter used to identify a cancel request.
* Default is "_cancel".
* <p>The parameter is recognized both when sent as a plain parameter
* ("_cancel") or when triggered by an image button ("_cancel.x").
*/
public final void setCancelParamKey(String cancelParamKey) {
this.cancelParamKey = cancelParamKey;
}
/**
* Return the key of the request parameter used to identify a cancel request.
*/
public final String getCancelParamKey() {
return this.cancelParamKey;
}
/**
* Sets the name of the cancel view.
*/
public final void setCancelView(String cancelView) {
this.cancelView = cancelView;
}
/**
* Gets the name of the cancel view.
*/
public final String getCancelView() {
return this.cancelView;
}
/**
* Consider an explicit cancel request as a form submission too.
* @see #isCancelRequest(javax.servlet.http.HttpServletRequest)
*/
@Override
protected boolean isFormSubmission(HttpServletRequest request) {
return super.isFormSubmission(request) || isCancelRequest(request);
}
/**
* Suppress validation for an explicit cancel request too.
* @see #isCancelRequest(javax.servlet.http.HttpServletRequest)
*/
@Override
protected boolean suppressValidation(HttpServletRequest request, Object command) {
return super.suppressValidation(request, command) || isCancelRequest(request);
}
/**
* This implementation first checks to see if the incoming is a cancel request,
* through a call to {@link #isCancelRequest}. If so, control is passed to
* {@link #onCancel}; otherwise, control is passed up to
* {@link SimpleFormController#processFormSubmission}.
* @see #isCancelRequest
* @see #onCancel(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, Object)
* @see SimpleFormController#processFormSubmission
*/
@Override
protected ModelAndView processFormSubmission(
HttpServletRequest request, HttpServletResponse response, Object command, BindException errors)
throws Exception {
if (isCancelRequest(request)) {
return onCancel(request, response, command);
}
else {
return super.processFormSubmission(request, response, command, errors);
}
}
/**
* Determine whether the incoming request is a request to cancel the
* processing of the current form.
* <p>By default, this method returns {@code true} if a parameter
* matching the configured {@code cancelParamKey} is present in
* the request, otherwise it returns {@code false}. Subclasses may
* override this method to provide custom logic to detect a cancel request.
* <p>The parameter is recognized both when sent as a plain parameter
* ("_cancel") or when triggered by an image button ("_cancel.x").
* @param request current HTTP request
* @see #setCancelParamKey
* @see #PARAM_CANCEL
*/
protected boolean isCancelRequest(HttpServletRequest request) {
return WebUtils.hasSubmitParameter(request, getCancelParamKey());
}
/**
* Callback method for handling a cancel request. Called if {@link #isCancelRequest}
* returns {@code true}.
* <p>Default implementation delegates to {@code onCancel(Object)} to return
* the configured {@code cancelView}. Subclasses may override either of the two
* methods to build a custom {@link ModelAndView ModelAndView} that may contain model
* parameters used in the cancel view.
* <p>If you simply want to move the user to a new view and you don't want to add
* additional model parameters, use {@link #setCancelView(String)} rather than
* overriding an {@code onCancel} method.
* @param request current servlet request
* @param response current servlet response
* @param command form object with request parameters bound onto it
* @return the prepared model and view, or {@code null}
* @throws Exception in case of errors
* @see #isCancelRequest(javax.servlet.http.HttpServletRequest)
* @see #onCancel(Object)
* @see #setCancelView
*/
protected ModelAndView onCancel(HttpServletRequest request, HttpServletResponse response, Object command)
throws Exception {
return onCancel(command);
}
/**
* Simple {@code onCancel} version. Called by the default implementation
* of the {@code onCancel} version with all parameters.
* <p>Default implementation returns eturns the configured {@code cancelView}.
* Subclasses may override this method to build a custom {@link ModelAndView ModelAndView}
* that may contain model parameters used in the cancel view.
* <p>If you simply want to move the user to a new view and you don't want to add
* additional model parameters, use {@link #setCancelView(String)} rather than
* overriding an {@code onCancel} method.
* @param command form object with request parameters bound onto it
* @return the prepared model and view, or {@code null}
* @throws Exception in case of errors
* @see #onCancel(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, Object)
* @see #setCancelView
*/
protected ModelAndView onCancel(Object command) throws Exception {
return new ModelAndView(getCancelView());
}
}
......@@ -60,7 +60,6 @@ import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.mvc.ParameterizableViewController;
import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.web.servlet.support.RequestContextUtils;
import org.springframework.web.servlet.theme.SessionThemeResolver;
import org.springframework.web.servlet.theme.ThemeChangeInterceptor;
......@@ -111,7 +110,7 @@ public class ComplexWebApplicationContext extends StaticWebApplicationContext {
pvs = new MutablePropertyValues();
pvs.add(
"mappings", "/form.do=formHandler\n/head.do=headController\n" +
"mappings", "/head.do=headController\n" +
"body.do=bodyController\n/noview*=noviewController\n/noview/simple*=noviewController");
pvs.add("order", "1");
registerSingleton("handlerMapping", SimpleUrlHandlerMapping.class, pvs);
......@@ -130,11 +129,6 @@ public class ComplexWebApplicationContext extends StaticWebApplicationContext {
pvs.add("suffix", ".jsp");
registerSingleton("viewResolver2", InternalResourceViewResolver.class, pvs);
pvs = new MutablePropertyValues();
pvs.add("commandClass", "org.springframework.tests.sample.beans.TestBean");
pvs.add("formView", "form");
registerSingleton("formHandler", SimpleFormController.class, pvs);
pvs = new MutablePropertyValues();
pvs.add("viewName", "form");
registerSingleton("viewHandler", ParameterizableViewController.class, pvs);
......
......@@ -18,7 +18,6 @@ package org.springframework.web.servlet;
import java.io.IOException;
import java.util.Locale;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
......@@ -31,7 +30,6 @@ import junit.framework.TestCase;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.DummyEnvironment;
import org.springframework.mock.web.test.MockHttpServletRequest;
......@@ -39,7 +37,6 @@ import org.springframework.mock.web.test.MockHttpServletResponse;
import org.springframework.mock.web.test.MockServletConfig;
import org.springframework.mock.web.test.MockServletContext;
import org.springframework.tests.sample.beans.TestBean;
import org.springframework.web.bind.EscapedErrors;
import org.springframework.web.context.ConfigurableWebEnvironment;
import org.springframework.web.context.ServletConfigAwareBean;
import org.springframework.web.context.ServletContextAwareBean;
......@@ -51,11 +48,8 @@ import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.mvc.BaseCommandController;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.support.RequestContext;
import org.springframework.web.servlet.support.RequestContextUtils;
import org.springframework.web.servlet.theme.AbstractThemeResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.util.WebUtils;
......@@ -155,44 +149,6 @@ public class DispatcherServletTests extends TestCase {
assertEquals(0, listener.counter);
}
public void testFormRequest() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/form.do");
request.addPreferredLocale(Locale.CANADA);
MockHttpServletResponse response = new MockHttpServletResponse();
simpleDispatcherServlet.service(request, response);
assertTrue("forwarded to form", "form".equals(response.getForwardedUrl()));
DefaultMessageSourceResolvable resolvable = new DefaultMessageSourceResolvable(new String[]{"test"});
RequestContext rc = new RequestContext(request);
assertTrue("hasn't RequestContext attribute", request.getAttribute("rc") == null);
assertTrue("Correct WebApplicationContext",
RequestContextUtils.getWebApplicationContext(request) instanceof SimpleWebApplicationContext);
assertTrue("Correct context path", rc.getContextPath().equals(request.getContextPath()));
assertTrue("Correct locale", Locale.CANADA.equals(RequestContextUtils.getLocale(request)));
assertTrue("Correct theme", AbstractThemeResolver.ORIGINAL_DEFAULT_THEME_NAME.equals(
RequestContextUtils.getTheme(request).getName()));
assertTrue("Correct message", "Canadian & test message".equals(rc.getMessage("test")));
assertTrue("Correct WebApplicationContext",
rc.getWebApplicationContext() == simpleDispatcherServlet.getWebApplicationContext());
assertTrue("Correct Errors",
!(rc.getErrors(BaseCommandController.DEFAULT_COMMAND_NAME) instanceof EscapedErrors));
assertTrue("Correct Errors",
!(rc.getErrors(BaseCommandController.DEFAULT_COMMAND_NAME, false) instanceof EscapedErrors));
assertTrue("Correct Errors",
rc.getErrors(BaseCommandController.DEFAULT_COMMAND_NAME, true) instanceof EscapedErrors);
assertEquals("Correct message", "Canadian & test message", rc.getMessage("test"));
assertEquals("Correct message", "Canadian & test message", rc.getMessage("test", null, false));
assertEquals("Correct message", "Canadian &amp; test message", rc.getMessage("test", null, true));
assertEquals("Correct message", "Canadian & test message", rc.getMessage(resolvable));
assertEquals("Correct message", "Canadian & test message", rc.getMessage(resolvable, false));
assertEquals("Correct message", "Canadian &amp; test message", rc.getMessage(resolvable, true));
assertEquals("Correct message", "Canadian & test message", rc.getMessage("test", "default"));
assertEquals("Correct message", "default", rc.getMessage("testa", "default"));
assertEquals("Correct message", "default &amp;", rc.getMessage("testa", null, "default &", true));
}
public void testParameterizableViewController() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/view.do");
request.addUserRole("role1");
......@@ -227,51 +183,6 @@ public class DispatcherServletTests extends TestCase {
assertTrue("Exception exposed", request.getAttribute("exception").getClass().equals(ServletException.class));
}
public void testAnotherFormRequest() throws Exception {
MockHttpServletRequest request =
new MockHttpServletRequest(getServletContext(), "GET", "/form.do;jsessionid=xxx");
request.addPreferredLocale(Locale.CANADA);
MockHttpServletResponse response = new MockHttpServletResponse();
complexDispatcherServlet.service(request, response);
assertTrue("forwarded to form", "myform.jsp".equals(response.getForwardedUrl()));
assertTrue("has RequestContext attribute", request.getAttribute("rc") != null);
DefaultMessageSourceResolvable resolvable = new DefaultMessageSourceResolvable(new String[]{"test"});
RequestContext rc = (RequestContext) request.getAttribute("rc");
assertTrue("Not in HTML escaping mode", !rc.isDefaultHtmlEscape());
assertTrue("Correct WebApplicationContext",
rc.getWebApplicationContext() == complexDispatcherServlet.getWebApplicationContext());
assertTrue("Correct context path", rc.getContextPath().equals(request.getContextPath()));
assertTrue("Correct locale", Locale.CANADA.equals(rc.getLocale()));
assertTrue("Correct Errors",
!(rc.getErrors(BaseCommandController.DEFAULT_COMMAND_NAME) instanceof EscapedErrors));
assertTrue("Correct Errors",
!(rc.getErrors(BaseCommandController.DEFAULT_COMMAND_NAME, false) instanceof EscapedErrors));
assertTrue("Correct Errors",
rc.getErrors(BaseCommandController.DEFAULT_COMMAND_NAME, true) instanceof EscapedErrors);
assertEquals("Correct message", "Canadian & test message", rc.getMessage("test"));
assertEquals("Correct message", "Canadian & test message", rc.getMessage("test", null, false));
assertEquals("Correct message", "Canadian &amp; test message", rc.getMessage("test", null, true));
assertEquals("Correct message", "Canadian & test message", rc.getMessage(resolvable));
assertEquals("Correct message", "Canadian & test message", rc.getMessage(resolvable, false));
assertEquals("Correct message", "Canadian &amp; test message", rc.getMessage(resolvable, true));
rc.setDefaultHtmlEscape(true);
assertTrue("Is in HTML escaping mode", rc.isDefaultHtmlEscape());
assertTrue("Correct Errors", rc.getErrors(BaseCommandController.DEFAULT_COMMAND_NAME) instanceof EscapedErrors);
assertTrue("Correct Errors",
!(rc.getErrors(BaseCommandController.DEFAULT_COMMAND_NAME, false) instanceof EscapedErrors));
assertTrue("Correct Errors",
rc.getErrors(BaseCommandController.DEFAULT_COMMAND_NAME, true) instanceof EscapedErrors);
assertEquals("Correct message", "Canadian &amp; test message", rc.getMessage("test"));
assertEquals("Correct message", "Canadian & test message", rc.getMessage("test", null, false));
assertEquals("Correct message", "Canadian &amp; test message", rc.getMessage("test", null, true));
assertEquals("Correct message", "Canadian &amp; test message", rc.getMessage(resolvable));
assertEquals("Correct message", "Canadian & test message", rc.getMessage(resolvable, false));
assertEquals("Correct message", "Canadian &amp; test message", rc.getMessage(resolvable, true));
}
public void testAnotherLocaleRequest() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/locale.do;abc=def");
request.addPreferredLocale(Locale.CANADA);
......@@ -568,7 +479,6 @@ public class DispatcherServletTests extends TestCase {
request = new MockHttpServletRequest(getServletContext(), "GET", "/form.do");
response = new MockHttpServletResponse();
complexDispatcherServlet.service(request, response);
assertTrue("forwarded to form", "myform.jsp".equals(response.getForwardedUrl()));
}
public void testNotDetectAllHandlerAdapters() throws ServletException, IOException {
......@@ -641,7 +551,6 @@ public class DispatcherServletTests extends TestCase {
request.setAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE, "/form.do");
simpleDispatcherServlet.service(request, response);
assertTrue("forwarded to form", "form".equals(response.getIncludedUrl()));
assertEquals("value1", request.getAttribute("test1"));
assertEquals("value2", request.getAttribute("test2"));
......@@ -663,12 +572,10 @@ public class DispatcherServletTests extends TestCase {
request.setAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE, "/form.do");
simpleDispatcherServlet.service(request, response);
assertTrue("forwarded to form", "form".equals(response.getIncludedUrl()));
assertEquals("value1", request.getAttribute("test1"));
assertEquals("value2", request.getAttribute("test2"));
assertSame(wac, request.getAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE));
assertSame(command, request.getAttribute("command"));
}
public void testNoCleanupAfterInclude() throws ServletException, IOException {
......@@ -685,12 +592,10 @@ public class DispatcherServletTests extends TestCase {
request.setAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE, "/form.do");
simpleDispatcherServlet.setCleanupAfterInclude(false);
simpleDispatcherServlet.service(request, response);
assertTrue("forwarded to form", "form".equals(response.getIncludedUrl()));
assertEquals("value1", request.getAttribute("test1"));
assertEquals("value2", request.getAttribute("test2"));
assertSame(wac, request.getAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE));
assertNotSame(command, request.getAttribute("command"));
}
public void testServletHandlerAdapter() throws Exception {
......
......@@ -34,7 +34,6 @@ import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.mvc.LastModified;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.web.servlet.support.RequestContextUtils;
import org.springframework.web.servlet.theme.AbstractThemeResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
......@@ -52,7 +51,6 @@ public class SimpleWebApplicationContext extends StaticWebApplicationContext {
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add("commandClass", "org.springframework.tests.sample.beans.TestBean");
pvs.add("formView", "form");
registerSingleton("/form.do", SimpleFormController.class, pvs);
registerSingleton("/locale.do", LocaleChecker.class);
......
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -16,12 +16,17 @@
package org.springframework.web.servlet.mvc.mapping;
import org.springframework.web.servlet.mvc.SimpleFormController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author Rob Harrop
*/
@Deprecated
public class BuyForm extends SimpleFormController {
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public class BuyForm implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
return null;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册