简体   繁体   中英

Disable Spring's implicit method dependency injection

I'm currently using Struts to develop an app, and the hello world page worked just fine until I made it extend ActionSupport to get access to i18n features. Upon doing this, the action started always returning input as the result string. This is obviously unexpected as there is no validation done at the moment. After debugging, I noticed that Spring decided to inject a field error map, so validation always sees something, causing the unexpected return value.

注射参数 ] 1

Here is the stack trace:

Daemon Thread [http-0.0.0.0-8080-2] (Suspended (breakpoint at line 79 in ActionSupport))    
Index(ActionSupport).setFieldErrors(Map<String,List<String>>) line: 79  
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]  
NativeMethodAccessorImpl.invoke(Object, Object[]) line: not available   
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: not available   
Method.invoke(Object, Object...) line: not available    
BeanWrapperImpl.setPropertyValue(BeanWrapperImpl$PropertyTokenHolder, PropertyValue) line: 1134 
BeanWrapperImpl.setPropertyValue(PropertyValue) line: 903   
BeanWrapperImpl(AbstractPropertyAccessor).setPropertyValues(PropertyValues, boolean, boolean) line: 75  
BeanWrapperImpl(AbstractPropertyAccessor).setPropertyValues(PropertyValues) line: 57    
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).applyPropertyValues(String, BeanDefinition, BeanWrapper, PropertyValues) line: 1450  
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).populateBean(String, RootBeanDefinition, BeanWrapper) line: 1158 
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).autowireBeanProperties(Object, int, boolean) line: 376   
StrutsSpringObjectFactory(SpringObjectFactory).autoWireBean(Object, AutowireCapableBeanFactory) line: 218   
StrutsSpringObjectFactory(SpringObjectFactory).buildBean(Class, Map<String,Object>) line: 198   
StrutsSpringObjectFactory(SpringObjectFactory).buildBean(String, Map<String,Object>, boolean) line: 164 
StrutsSpringObjectFactory(ObjectFactory).buildBean(String, Map<String,Object>) line: 178    
DefaultActionFactory.buildAction(String, String, ActionConfig, Map<String,Object>) line: 22 
StrutsSpringObjectFactory(ObjectFactory).buildAction(String, String, ActionConfig, Map<String,Object>) line: 148    
DefaultActionInvocation.createAction(Map<String,Object>) line: 295  
DefaultActionInvocation.init(ActionProxy) line: 395 
StrutsActionProxy(DefaultActionProxy).prepare() line: 194   
StrutsActionProxy.prepare() line: 63    
StrutsActionProxyFactory.createActionProxy(ActionInvocation, String, String, String, boolean, boolean) line: 37 
StrutsActionProxyFactory(DefaultActionProxyFactory).createActionProxy(String, String, String, Map<String,Object>, boolean, boolean) line: 58    
Dispatcher.serviceAction(HttpServletRequest, HttpServletResponse, ActionMapping) line: 554  
ExecuteOperations.executeAction(HttpServletRequest, HttpServletResponse, ActionMapping) line: 81    
StrutsPrepareAndExecuteFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 99   
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 235  
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 206  
OpenSessionInViewFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 232    
OpenSessionInViewFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 106  
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 235  
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 206  
ReplyHeaderFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 96   
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 235  
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 206  
StandardWrapperValve.invoke(Request, Response) line: 230    
StandardContextValve.invoke(Request, Response) line: 175    
SecurityAssociationValve.invoke(Request, Response) line: 182    
JaccContextValve.invoke(Request, Response) line: 84 
StandardHostValve.invoke(Request, Response) line: 127   
ErrorReportValve.invoke(Request, Response) line: 102    
CachedConnectionValve.invoke(Request, Response) line: 157   
StandardEngineValve.invoke(Request, Response) line: 109 
CoyoteAdapter.service(Request, Response) line: 262  
Http11Processor.process(Socket) line: 844   
Http11Protocol$Http11ConnectionHandler.process(Socket) line: 583    
JIoEndpoint$Worker.run() line: 446  
Thread.run() line: not available    

This is basically all that the class contains:

public class Index extends ActionSupport implements UserAware
{
    private User user;


    @Override
    public String execute()
    {
        System.out.println("this doesn't print out");
        return "SUCCESS";
    }

    @Override
    public void setUser(User user)
    {
        this.user = user;
    }

    public User getUser()
    {
        return user;
    }
}

I'm only using the @Autowired annotated property injection, so I'd like to disable the method injection to fix this issue. That is of course if that is the problem. I could have misinterpreted the symptoms.

Versions

  • Spring 3.2.9
  • Struts 2.3.24

Struts and Spring does not go well together by default, You need to add struts2-spring-plugin-xyzjar in your WEB-INF/lib from your struts lib directory. and configure it properly in web.xml, refer this http://www.tutorialspoint.com/struts_2/struts_spring.htm

This happens due to ActionSupport implements all interfaces required for validation, like Validatable and ValidationAware .

ValidationAware classes can accept Action (class level) or field level error messages. Action level messages are kept in a Collection . Field level error messages are kept in a Map from String field name to a List of field error messages.

The last one is more specific to injection of errors but it's not a Spring job (Spring uses its object factory to build the action and inject its dependencies), it's a Struts job to support the action with field errors and action errors, and it's well done with the validation interceptor.

This interceptor runs the action through the standard validation framework, which in turn checks the action against any validation rules (found in files such as ActionClass-validation.xml ) and adds field-level and action-level error messages (provided that the action implements com.opensymphony.xwork2.ValidationAware ).

The validation interceptor is included in the defaultStack which is used by default in any action. If the action doesn't need the validation capabilities you can remove this interceptor from the stack by creating a new stack, or overriding the action config. If the validation is provided to other methods, then you can exclude some methods from the interceptor or apply a @SkipValidation annotation. That would disable the validation from the method of the action.

I was able to fix this by changing the autowire type to none in the struts.xml file. I initially set it to type because I thought that @Autowire injection wouldn't work otherwise. I guess I was wrong since those injections still work.

<constant name="struts.objectFactory.spring.autoWire" value="type" />

to

<constant name="struts.objectFactory.spring.autoWire" value="none" />

Thanks to all participants for helping.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM