001: /*
002: * Copyright 2002-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.web.struts;
018:
019: import java.io.IOException;
020:
021: import javax.servlet.ServletException;
022: import javax.servlet.http.HttpServletRequest;
023: import javax.servlet.http.HttpServletResponse;
024:
025: import org.apache.struts.action.Action;
026: import org.apache.struts.action.ActionMapping;
027: import org.apache.struts.action.ActionServlet;
028: import org.apache.struts.action.RequestProcessor;
029: import org.apache.struts.config.ModuleConfig;
030:
031: import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
032: import org.springframework.context.ConfigurableApplicationContext;
033: import org.springframework.web.context.WebApplicationContext;
034:
035: /**
036: * Subclass of Struts's default RequestProcessor that autowires Struts Actions
037: * with Spring beans defined in ContextLoaderPlugIn's WebApplicationContext
038: * or - in case of general service layer beans - in the root WebApplicationContext.
039: *
040: * <p>In the Struts config file, you simply continue to specify the original
041: * Action class. The instance created for that class will automatically get
042: * wired with matching service layer beans, that is, bean property setters
043: * will automatically be called if a service layer bean matches the property.
044: *
045: * <pre>
046: * <action path="/login" type="myapp.MyAction"/></pre>
047: *
048: * There are two autowire modes available: "byType" and "byName". The default
049: * is "byType", matching service layer beans with the Action's bean property
050: * argument types. This behavior can be changed through specifying an "autowire"
051: * init-param for the Struts ActionServlet with the value "byName", which will
052: * match service layer bean names with the Action's bean property <i>names</i>.
053: *
054: * <p>Dependency checking is turned off by default: If no matching service
055: * layer bean can be found, the setter in question will simply not get invoked.
056: * To enforce matching service layer beans, consider specify the "dependencyCheck"
057: * init-param for the Struts ActionServlet with the value "true".
058: *
059: * <p>If you also need the Tiles setup functionality of the original
060: * TilesRequestProcessor, use AutowiringTilesRequestProcessor. As there's just
061: * a single central class to customize in Struts, we have to provide another
062: * subclass here, covering both the Tiles and the Spring delegation aspect.
063: *
064: * <p>The default implementation delegates to the DelegatingActionUtils
065: * class as fas as possible, to reuse as much code as possible despite
066: * the need to provide two RequestProcessor subclasses. If you need to
067: * subclass yet another RequestProcessor, take this class as a template,
068: * delegating to DelegatingActionUtils just like it.
069: *
070: * @author Juergen Hoeller
071: * @since 2.0
072: * @see AutowiringTilesRequestProcessor
073: * @see ContextLoaderPlugIn
074: * @see DelegatingActionUtils
075: */
076: public class AutowiringRequestProcessor extends RequestProcessor {
077:
078: private WebApplicationContext webApplicationContext;
079:
080: private int autowireMode = AutowireCapableBeanFactory.AUTOWIRE_NO;
081:
082: private boolean dependencyCheck = false;
083:
084: public void init(ActionServlet actionServlet,
085: ModuleConfig moduleConfig) throws ServletException {
086: super .init(actionServlet, moduleConfig);
087: if (actionServlet != null) {
088: this .webApplicationContext = initWebApplicationContext(
089: actionServlet, moduleConfig);
090: this .autowireMode = initAutowireMode(actionServlet,
091: moduleConfig);
092: this .dependencyCheck = initDependencyCheck(actionServlet,
093: moduleConfig);
094: }
095: }
096:
097: /**
098: * Fetch ContextLoaderPlugIn's WebApplicationContext from the ServletContext,
099: * falling back to the root WebApplicationContext. This context is supposed
100: * to contain the service layer beans to wire the Struts Actions with.
101: * @param actionServlet the associated ActionServlet
102: * @param moduleConfig the associated ModuleConfig
103: * @return the WebApplicationContext
104: * @throws IllegalStateException if no WebApplicationContext could be found
105: * @see DelegatingActionUtils#findRequiredWebApplicationContext
106: * @see ContextLoaderPlugIn#SERVLET_CONTEXT_PREFIX
107: */
108: protected WebApplicationContext initWebApplicationContext(
109: ActionServlet actionServlet, ModuleConfig moduleConfig)
110: throws IllegalStateException {
111:
112: WebApplicationContext wac = DelegatingActionUtils
113: .findRequiredWebApplicationContext(actionServlet,
114: moduleConfig);
115: if (wac instanceof ConfigurableApplicationContext) {
116: ((ConfigurableApplicationContext) wac).getBeanFactory()
117: .ignoreDependencyType(ActionServlet.class);
118: }
119: return wac;
120: }
121:
122: /**
123: * Determine the autowire mode to use for wiring Struts Actions.
124: * <p>The default implementation checks the "autowire" init-param of the
125: * Struts ActionServlet, falling back to "AUTOWIRE_BY_TYPE" as default.
126: * @param actionServlet the associated ActionServlet
127: * @param moduleConfig the associated ModuleConfig
128: * @return the autowire mode to use
129: * @see DelegatingActionUtils#getAutowireMode
130: * @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#autowireBeanProperties
131: * @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#AUTOWIRE_BY_TYPE
132: * @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#AUTOWIRE_BY_NAME
133: */
134: protected int initAutowireMode(ActionServlet actionServlet,
135: ModuleConfig moduleConfig) {
136: return DelegatingActionUtils.getAutowireMode(actionServlet);
137: }
138:
139: /**
140: * Determine whether to apply a dependency check after wiring Struts Actions.
141: * <p>The default implementation checks the "dependencyCheck" init-param of the
142: * Struts ActionServlet, falling back to no dependency check as default.
143: * @param actionServlet the associated ActionServlet
144: * @param moduleConfig the associated ModuleConfig
145: * @return whether to enforce a dependency check or not
146: * @see DelegatingActionUtils#getDependencyCheck
147: * @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#autowireBeanProperties
148: */
149: protected boolean initDependencyCheck(ActionServlet actionServlet,
150: ModuleConfig moduleConfig) {
151: return DelegatingActionUtils.getDependencyCheck(actionServlet);
152: }
153:
154: /**
155: * Return the current Spring WebApplicationContext.
156: */
157: protected final WebApplicationContext getWebApplicationContext() {
158: return this .webApplicationContext;
159: }
160:
161: /**
162: * Return the autowire mode to use for wiring Struts Actions.
163: */
164: protected final int getAutowireMode() {
165: return autowireMode;
166: }
167:
168: /**
169: * Return whether to apply a dependency check after wiring Struts Actions.
170: */
171: protected final boolean getDependencyCheck() {
172: return dependencyCheck;
173: }
174:
175: /**
176: * Extend the base class method to autowire each created Action instance.
177: * @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#autowireBeanProperties
178: */
179: protected Action processActionCreate(HttpServletRequest request,
180: HttpServletResponse response, ActionMapping mapping)
181: throws IOException {
182:
183: Action action = super.processActionCreate(request, response,
184: mapping);
185: getWebApplicationContext().getAutowireCapableBeanFactory()
186: .autowireBeanProperties(action, getAutowireMode(),
187: getDependencyCheck());
188: return action;
189: }
190:
191: }
|