View Javadoc

1   /*
2    * $Id: StrutsSpringObjectFactory.java 817418 2009-09-21 21:36:17Z musachy $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  package org.apache.struts2.spring;
23  
24  import com.opensymphony.xwork2.inject.Container;
25  import com.opensymphony.xwork2.inject.Inject;
26  import com.opensymphony.xwork2.spring.SpringObjectFactory;
27  import com.opensymphony.xwork2.util.logging.Logger;
28  import com.opensymphony.xwork2.util.logging.LoggerFactory;
29  import org.apache.struts2.StrutsConstants;
30  import org.apache.commons.lang.xwork.StringUtils;
31  import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
32  import org.springframework.context.ApplicationContext;
33  import org.springframework.web.context.WebApplicationContext;
34  
35  import javax.servlet.ServletContext;
36  
37  
38  
39  /***
40   * Struts object factory that integrates with Spring.
41   * <p/>
42   * Spring should be loaded using a web context listener
43   * <code>org.springframework.web.context.ContextLoaderListener</code> defined in <code>web.xml</code>.
44   *
45   */
46  public class StrutsSpringObjectFactory extends SpringObjectFactory {
47      private static final Logger LOG = LoggerFactory.getLogger(StrutsSpringObjectFactory.class);
48  
49      //@Inject
50      //public StrutsSpringObjectFactory(
51      //        @Inject(value=StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE,required=false) String autoWire,
52      //        @Inject(value=StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_USE_CLASS_CACHE,required=false) String useClassCacheStr,
53      //        @Inject ServletContext servletContext) {
54      //    this(autoWire, "false", useClassCacheStr, servletContext);
55      //}
56  
57      /***
58       * Constructs the spring object factory
59       * @param autoWire The type of autowiring to use
60       * @param alwaysAutoWire Whether to always respect the autowiring or not
61       * @param useClassCacheStr Whether to use the class cache or not
62       * @param servletContext The servlet context
63       * @since 2.1.3
64       */
65      @Inject
66      public StrutsSpringObjectFactory(
67              @Inject(value=StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE,required=false) String autoWire,
68              @Inject(value=StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE_ALWAYS_RESPECT,required=false) String alwaysAutoWire,
69              @Inject(value=StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_USE_CLASS_CACHE,required=false) String useClassCacheStr,
70              @Inject ServletContext servletContext,
71              @Inject(StrutsConstants.STRUTS_DEVMODE) String devMode,
72              @Inject Container container) {
73            
74          super();
75          boolean useClassCache = "true".equals(useClassCacheStr);
76          LOG.info("Initializing Struts-Spring integration...");
77  
78          Object rootWebApplicationContext =  servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
79  
80          if(rootWebApplicationContext instanceof RuntimeException){
81              RuntimeException runtimeException = (RuntimeException)rootWebApplicationContext;
82              LOG.fatal(runtimeException.getMessage());
83              return;
84          }
85  
86          ApplicationContext appContext = (ApplicationContext) rootWebApplicationContext;
87          if (appContext == null) {
88              // uh oh! looks like the lifecycle listener wasn't installed. Let's inform the user
89              String message = "********** FATAL ERROR STARTING UP STRUTS-SPRING INTEGRATION **********\n" +
90                      "Looks like the Spring listener was not configured for your web app! \n" +
91                      "Nothing will work until WebApplicationContextUtils returns a valid ApplicationContext.\n" +
92                      "You might need to add the following to web.xml: \n" +
93                      "    <listener>\n" +
94                      "        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>\n" +
95                      "    </listener>";
96              LOG.fatal(message);
97              return;
98          }
99          
100         String watchList = container.getInstance(String.class, "struts.class.reloading.watchList");
101         String acceptClasses = container.getInstance(String.class, "struts.class.reloading.acceptClasses");
102         String reloadConfig = container.getInstance(String.class, "struts.class.reloading.reloadConfig");
103 
104         if ("true".equals(devMode)
105                 && StringUtils.isNotBlank(watchList)
106                 && appContext instanceof ClassReloadingXMLWebApplicationContext) {
107             //prevent class caching
108             useClassCache = false;
109 
110             ClassReloadingXMLWebApplicationContext reloadingContext = (ClassReloadingXMLWebApplicationContext) appContext;
111             reloadingContext.setupReloading(watchList.split(","), acceptClasses, servletContext, "true".equals(reloadConfig));
112             LOG.info("Class reloading is enabled. Make sure this is not used on a production environment!", watchList);
113 
114             setClassLoader(reloadingContext.getReloadingClassLoader());
115 
116             //we need to reload the context, so our isntance of the factory is picked up
117             reloadingContext.refresh();
118         }
119 
120         this.setApplicationContext(appContext);
121 
122         int type = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;   // default
123         if ("name".equals(autoWire)) {
124             type = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
125         } else if ("type".equals(autoWire)) {
126             type = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
127         } else if ("auto".equals(autoWire)) {
128             type = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
129         } else if ("constructor".equals(autoWire)) {
130             type = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
131         } else if ("no".equals(autoWire)) {
132             type = AutowireCapableBeanFactory.AUTOWIRE_NO;
133         }
134         this.setAutowireStrategy(type);
135 
136         this.setUseClassCache(useClassCache);
137 
138         this.setAlwaysRespectAutowireStrategy("true".equalsIgnoreCase(alwaysAutoWire));
139 
140         LOG.info("... initialized Struts-Spring integration successfully");
141     }
142 }