|
Spring Framework example source code file (AnnotationMethodHandlerAdapter.java)
The Spring Framework AnnotationMethodHandlerAdapter.java source code/* * Copyright 2002-2008 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.annotation; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; import java.lang.reflect.Method; import java.security.Principal; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.Locale; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.PortalContext; import javax.portlet.PortletException; import javax.portlet.PortletMode; import javax.portlet.PortletPreferences; import javax.portlet.PortletRequest; import javax.portlet.PortletResponse; import javax.portlet.PortletSession; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import javax.portlet.UnavailableException; import javax.portlet.WindowState; import org.springframework.beans.BeanUtils; import org.springframework.core.Conventions; import org.springframework.core.GenericTypeResolver; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.core.MethodParameter; import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.style.StylerUtils; import org.springframework.ui.ExtendedModelMap; import org.springframework.ui.Model; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.SessionAttributes; import org.springframework.web.bind.annotation.support.HandlerMethodInvoker; import org.springframework.web.bind.annotation.support.HandlerMethodResolver; import org.springframework.web.bind.support.DefaultSessionAttributeStore; import org.springframework.web.bind.support.SessionAttributeStore; import org.springframework.web.bind.support.WebArgumentResolver; import org.springframework.web.bind.support.WebBindingInitializer; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.portlet.HandlerAdapter; import org.springframework.web.portlet.ModelAndView; import org.springframework.web.portlet.bind.MissingPortletRequestParameterException; import org.springframework.web.portlet.bind.PortletRequestDataBinder; import org.springframework.web.portlet.context.PortletWebRequest; import org.springframework.web.portlet.handler.PortletContentGenerator; import org.springframework.web.portlet.handler.PortletSessionRequiredException; import org.springframework.web.portlet.util.PortletUtils; import org.springframework.web.servlet.View; /** * Implementation of the {@link org.springframework.web.portlet.HandlerAdapter} * interface that maps handler methods based on portlet modes, action/render phases * and request parameters expressed through the {@link RequestMapping} annotation. * * <p>Supports request parameter binding through the {@link RequestParam} annotation. * Also supports the {@link ModelAttribute} annotation for exposing model attribute * values to the view, as well as {@link InitBinder} for binder initialization methods * and {@link SessionAttributes} for automatic session management of specific attributes. * * <p>This adapter can be customized through various bean properties. * A common use case is to apply shared binder initialization logic through * a custom {@link #setWebBindingInitializer WebBindingInitializer}. * * @author Juergen Hoeller * @author Arjen Poutsma * @since 2.5 * @see #setWebBindingInitializer * @see #setSessionAttributeStore */ public class AnnotationMethodHandlerAdapter extends PortletContentGenerator implements HandlerAdapter { private static final String IMPLICIT_MODEL_ATTRIBUTE = "org.springframework.web.portlet.mvc.ImplicitModel"; private WebBindingInitializer webBindingInitializer; private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore(); private boolean synchronizeOnSession = false; private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer(); private WebArgumentResolver[] customArgumentResolvers; private final Map<Class methodResolverCache = new ConcurrentHashMap<Class(); /** * Specify a WebBindingInitializer which will apply pre-configured * configuration to every DataBinder that this controller uses. */ public void setWebBindingInitializer(WebBindingInitializer webBindingInitializer) { this.webBindingInitializer = webBindingInitializer; } /** * Specify the strategy to store session attributes with. * <p>Default is {@link org.springframework.web.bind.support.DefaultSessionAttributeStore}, * storing session attributes in the PortletSession, using the same * attribute name as in the model. */ public void setSessionAttributeStore(SessionAttributeStore sessionAttributeStore) { Assert.notNull(sessionAttributeStore, "SessionAttributeStore must not be null"); this.sessionAttributeStore = sessionAttributeStore; } /** * Set if controller execution should be synchronized on the session, * to serialize parallel invocations from the same client. * <p>More specifically, the execution of each handler method will get * synchronized if this flag is "true". The best available session mutex * will be used for the synchronization; ideally, this will be a mutex * exposed by HttpSessionMutexListener. * <p>The session mutex is guaranteed to be the same object during * the entire lifetime of the session, available under the key defined * by the <code>SESSION_MUTEX_ATTRIBUTE constant. It serves as a * safe reference to synchronize on for locking on the current session. * <p>In many cases, the PortletSession reference itself is a safe mutex * as well, since it will always be the same object reference for the * same active logical session. However, this is not guaranteed across * different servlet containers; the only 100% safe way is a session mutex. * @see org.springframework.web.util.HttpSessionMutexListener * @see org.springframework.web.portlet.util.PortletUtils#getSessionMutex(javax.portlet.PortletSession) */ public void setSynchronizeOnSession(boolean synchronizeOnSession) { this.synchronizeOnSession = synchronizeOnSession; } /** * Set the ParameterNameDiscoverer to use for resolving method parameter * names if needed (e.g. for default attribute names). * <p>Default is a {@link org.springframework.core.LocalVariableTableParameterNameDiscoverer}. */ public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) { this.parameterNameDiscoverer = parameterNameDiscoverer; } /** * Set a custom ArgumentResolvers to use for special method parameter types. * Such a custom ArgumentResolver will kick in first, having a chance to * resolve an argument value before the standard argument handling kicks in. */ public void setCustomArgumentResolver(WebArgumentResolver argumentResolver) { this.customArgumentResolvers = new WebArgumentResolver[] {argumentResolver}; } /** * Set one or more custom ArgumentResolvers to use for special method * parameter types. Any such custom ArgumentResolver will kick in first, * having a chance to resolve an argument value before the standard * argument handling kicks in. */ public void setCustomArgumentResolvers(WebArgumentResolver[] argumentResolvers) { this.customArgumentResolvers = argumentResolvers; } public boolean supports(Object handler) { return getMethodResolver(handler).hasHandlerMethods(); } public void handleAction(ActionRequest request, ActionResponse response, Object handler) throws Exception { Object returnValue = doHandle(request, response, handler); if (returnValue != null) { throw new IllegalStateException("Invalid action method return value: " + returnValue); } } public ModelAndView handleRender(RenderRequest request, RenderResponse response, Object handler) throws Exception { checkAndPrepare(request, response); return doHandle(request, response, handler); } protected ModelAndView doHandle(PortletRequest request, PortletResponse response, Object handler) throws Exception { ExtendedModelMap implicitModel = null; if (request instanceof RenderRequest && response instanceof RenderResponse) { RenderRequest renderRequest = (RenderRequest) request; RenderResponse renderResponse = (RenderResponse) response; // Detect implicit model from associated action phase. if (renderRequest.getParameter(IMPLICIT_MODEL_ATTRIBUTE) != null) { PortletSession session = request.getPortletSession(false); if (session != null) { implicitModel = (ExtendedModelMap) session.getAttribute(IMPLICIT_MODEL_ATTRIBUTE); } } if (handler.getClass().getAnnotation(SessionAttributes.class) != null) { // Always prevent caching in case of session attribute management. checkAndPrepare(renderRequest, renderResponse, 0); } else { // Uses configured default cacheSeconds setting. checkAndPrepare(renderRequest, renderResponse); } } if (implicitModel == null) { implicitModel = new ExtendedModelMap(); } // Execute invokeHandlerMethod in synchronized block if required. if (this.synchronizeOnSession) { PortletSession session = request.getPortletSession(false); if (session != null) { Object mutex = PortletUtils.getSessionMutex(session); synchronized (mutex) { return invokeHandlerMethod(request, response, handler, implicitModel); } } } return invokeHandlerMethod(request, response, handler, implicitModel); } private ModelAndView invokeHandlerMethod( PortletRequest request, PortletResponse response, Object handler, ExtendedModelMap implicitModel) throws Exception { PortletWebRequest webRequest = new PortletWebRequest(request, response); PortletHandlerMethodResolver methodResolver = getMethodResolver(handler); Method handlerMethod = methodResolver.resolveHandlerMethod(request, response); PortletHandlerMethodInvoker methodInvoker = new PortletHandlerMethodInvoker(methodResolver); Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel); ModelAndView mav = methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel); methodInvoker.updateModelAttributes( handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest); // Expose implicit model for subsequent render phase. if (response instanceof ActionResponse && !implicitModel.isEmpty()) { ActionResponse actionResponse = (ActionResponse) response; try { actionResponse.setRenderParameter(IMPLICIT_MODEL_ATTRIBUTE, Boolean.TRUE.toString()); request.getPortletSession().setAttribute(IMPLICIT_MODEL_ATTRIBUTE, implicitModel); } catch (IllegalStateException ex) { // Probably sendRedirect called... no need to expose model to render phase. } } return mav; } /** * Template method for creating a new PortletRequestDataBinder instance. * <p>The default implementation creates a standard PortletRequestDataBinder. * This can be overridden for custom PortletRequestDataBinder subclasses. * @param request current portlet request * @param target the target object to bind onto (or <code>null * if the binder is just used to convert a plain parameter value) * @param objectName the objectName of the target object * @return the PortletRequestDataBinder instance to use * @throws Exception in case of invalid state or arguments * @see PortletRequestDataBinder#bind(javax.portlet.PortletRequest) * @see PortletRequestDataBinder#convertIfNecessary(Object, Class, MethodParameter) */ protected PortletRequestDataBinder createBinder( PortletRequest request, Object target, String objectName) throws Exception { return new PortletRequestDataBinder(target, objectName); } /** * Build a HandlerMethodResolver for the given handler type. */ private PortletHandlerMethodResolver getMethodResolver(Object handler) { Class handlerClass = ClassUtils.getUserClass(handler); PortletHandlerMethodResolver resolver = this.methodResolverCache.get(handlerClass); if (resolver == null) { resolver = new PortletHandlerMethodResolver(handlerClass); this.methodResolverCache.put(handlerClass, resolver); } return resolver; } private static class PortletHandlerMethodResolver extends HandlerMethodResolver { public PortletHandlerMethodResolver(Class<?> handlerType) { super(handlerType); } public Method resolveHandlerMethod(PortletRequest request, PortletResponse response) throws PortletException { String lookupMode = request.getPortletMode().toString(); Map<RequestMappingInfo, Method> targetHandlerMethods = new LinkedHashMap Other Spring Framework examples (source code examples)Here is a short list of links related to this Spring Framework AnnotationMethodHandlerAdapter.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.