设置StrutsSpringObjectFactory作为我当前的对象工厂



我正在做一个使用openSymphony 2.1.2和struts 2.3.8的项目。

然而,在这个代码基础上,我试图应用一段代码,这是为旧版本的openSymphony和struts编写的。

下面是这段代码:

http://www.lischke-online.de/index.php/java/action-unit-testing-with-struts-2-0-part-2

(作为旁注,我需要这些代码,以便能够在基于不同框架的系统中模拟从继承的项目中运行struts动作。)

我对以下段落有一个问题:

final StrutsSpringObjectFactory ssf = new StrutsSpringObjectFactory("auto", "true", servletContext);
ObjectFactory.setObjectFactory(ssf);

在第二行,我得到错误:The method setObjectFactory(StrutsSpringObjectFactory) is undefined for the type ObjectFactory

然而,当我查看ObjectFactory的javadoc时,我没有看到一个替代方法可以让我设置一个特定的ObjectFactory(例如StrutsSpringObjectFactory),作为执行动作时将使用的ObjectFactory。那么,如何使用新API设置这样一个特定的ObjectFactory呢?

更新代码:

static {
    sessionMap = new HashMap<String, Object>();
    // Create fake back end here.
    // ...
    // ===== Struts setup:
    // Create and use a file system resource loader otherwise Tiles will not find
    // our configuration file. The default resource loader is able to find struts.xml
    // if it is in the classpath, but not tiles.xml.
    final FileSystemResourceLoader loader = new FileSystemResourceLoader();
    final String[] config = new String[] { "WEB-INF/classes/struts.xml" };
    servletContext = new MockServletContext(loader);
    final XmlWebApplicationContext appContext = new XmlWebApplicationContext();
    // Link the servlet context and the Spring context.
    appContext.setServletContext(servletContext);
    appContext.setConfigLocations(config);
    appContext.refresh();
    servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
        appContext);
    servletContext.addInitParameter(BasicTilesContainer.DEFINITIONS_CONFIG, "WEB-INF/tiles.xml");
    // Creating the tiles listener statically (not via class loader).
    final StrutsTilesListener tilesListener = new StrutsTilesListener();
    final ServletContextEvent event = new ServletContextEvent(servletContext);
    tilesListener.contextInitialized(event);
    // Use spring as the object factory for Struts
    //this code not working anymore with struts 2.3.2:
    //final StrutsSpringObjectFactory ssf = new StrutsSpringObjectFactory("auto", "true", servletContext);
    //ObjectFactory.setObjectFactory(ssf);
    //my change: (original note working with newer version of struts)
    //StrutsSpringObjectFactory.setObjectFactory(ssf);
    //(*) original location.
    // Dispatcher is the guy that actually handles all requests. Pass in
    // an empty. Map as the parameters but if you want to change stuff like
    // what config files to read, you need to specify them here
    // (see Dispatcher's source code)
    dispatcher = new Dispatcher(servletContext, new HashMap<String, String>()); 
    dispatcher.init();
    Dispatcher.setInstance(dispatcher);
    //(*) moved to here:
    //http://stackoverflow.com/questions/15821643/setting-strutsspringobjectfactory-as-my-current-objectfactory?noredirect=1#comment22519072_15821643
    final StrutsSpringObjectFactory ssf = new StrutsSpringObjectFactory("auto", "true", "false", servletContext, "false", dispatcher.getContainer());
}

当从web应用程序(部署的war)中调用测试时,我在该代码上获得的堆栈跟踪:

08:50:28,471 WARNING [javax.enterprise.resource.webcontainer.jsf.lifecycle] (http--127.0.0.1-8080-1) #{accountLookupBean.lookupAccounts()}: java.lang.ExceptionInInitial
izerError: javax.faces.FacesException: #{accountLookupBean.lookupAccounts()}: java.lang.ExceptionInInitializerError
        at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118) [jsf-impl-2.1.5-jbossorg-1.jar:2.1.5-SNAPSHOT]
        at javax.faces.component.UICommand.broadcast(UICommand.java:315) [jboss-jsf-api_2.1_spec-2.0.0.Final.jar:2.0.0.Final]
        at javax.faces.component.UIData.broadcast(UIData.java:1093) [jboss-jsf-api_2.1_spec-2.0.0.Final.jar:2.0.0.Final]
        at javax.faces.component.UIData.broadcast(UIData.java:1093) [jboss-jsf-api_2.1_spec-2.0.0.Final.jar:2.0.0.Final]
        at javax.faces.component.UIData.broadcast(UIData.java:1093) [jboss-jsf-api_2.1_spec-2.0.0.Final.jar:2.0.0.Final]
        at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794) [jboss-jsf-api_2.1_spec-2.0.0.Final.jar:2.0.0.Final]
        at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259) [jboss-jsf-api_2.1_spec-2.0.0.Final.jar:2.0.0.Final]
        at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81) [jsf-impl-2.1.5-jbossorg-1.jar:2.1.5-SNAPSHOT]
        at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) [jsf-impl-2.1.5-jbossorg-1.jar:2.1.5-SNAPSHOT]
        at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) [jsf-impl-2.1.5-jbossorg-1.jar:2.1.5-SNAPSHOT]
        at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593) [jboss-jsf-api_2.1_spec-2.0.0.Final.jar:2.0.0.Final]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.10.Final.jar:]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.10.Final.jar:]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.10.Final.jar:]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.10.Final.jar:]
        at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:154) [jboss-as-web-7.1.0.Final.jar:7.1.0.Final]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.10.Final.jar:]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.10.Final.jar:]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.10.Final.jar:]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.10.Final.jar:]
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.10.Final.jar:]
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.10.Final.jar:]
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.10.Final.jar:]
        at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_29]
Caused by: javax.faces.el.EvaluationException: java.lang.ExceptionInInitializerError
        at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102) [jboss-jsf-api_2.1_spec-2.0.0.Final.jar:2.0.
0.Final]
        at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102) [jsf-impl-2.1.5-jbossorg-1.jar:2.1.5-SNAPSHOT]
        ... 23 more
Caused by: java.lang.ExceptionInInitializerError
        at com.myapp.services.AccountLookupServiceImpl.getRows(AccountLookupServiceImpl.java:38) [classes:]
        at com.myapp.beans.AccountLookupBean.lookupAccounts(AccountLookupBean.java:39) [classes:]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.6.0_29]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [rt.jar:1.6.0_29]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [rt.jar:1.6.0_29]
        at java.lang.reflect.Method.invoke(Method.java:597) [rt.jar:1.6.0_29]
        at org.apache.el.parser.AstValue.invoke(AstValue.java:262) [jbossweb-7.0.10.Final.jar:]
        at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278) [jbossweb-7.0.10.Final.jar:]
        at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105) [jsf-impl-2.1.5-jbossorg-1.jar:2.1.5-SNAPSHOT]
        at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88) [jboss-jsf-api_2.1_spec-2.0.0.Final.jar:2.0.0
.Final]
        ... 24 more
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from ServletContext resource [/WEB-INF/classes/struts.xml];
nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/classes/struts.xml]
        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:341) [spring-beans-3.2.1.RELEASE.jar:3.2.1.REL
EASE]
        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302) [spring-beans-3.2.1.RELEASE.jar:3.2.1.REL
EASE]
        at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:174) [spring-beans-3.2.1.RELEASE
.jar:3.2.1.RELEASE]
        at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:209) [spring-beans-3.2.1.RELEASE
.jar:3.2.1.RELEASE]
        at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:180) [spring-beans-3.2.1.RELEASE
.jar:3.2.1.RELEASE]
        at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:125) [spring-web-3.2.1.RELEASE.jar:3.2.1.R
ELEASE]
        at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:94) [spring-web-3.2.1.RELEASE.jar:3.2.1.RE
LEASE]
        at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:130) [spring-context-
3.2.1.RELEASE.jar:3.2.1.RELEASE]
        at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:537) [spring-context-3.2.1.RELEASE.jar:
3.2.1.RELEASE]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:451) [spring-context-3.2.1.RELEASE.jar:3.2.1.RELEASE]
        at com.myapp.softgems.ActionBaseTestCase.<clinit>(ActionBaseTestCase.java:70) [classes:]
        ... 34 more
Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/classes/struts.xml]
        at org.springframework.web.context.support.ServletContextResource.getInputStream(ServletContextResource.java:140) [spring-web-3.2.1.RELEASE.jar:3.2.1.RELEASE]
        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:328) [spring-beans-3.2.1.RELEASE.jar:3.2.1.REL
EASE]
        ... 44 more
更新2:

我想要能够测试一个动作的原因,不是简单地能够从项目资源管理器右键单击它,然后右键单击"作为Junit运行"。我实际上想运行测试作为我的web应用程序的一部分。

这就是我的意思:我正试图从我的一个服务类中调用以下代码:

DataTest test = new DataTest("testDataAction");
JUnitCore jUnitCore = new JUnitCore();
jUnitCore.run(test);

因为,在DataTest中我尝试执行()DataAction。该Action调用一些混乱的db逻辑并最终返回一些数据。我的服务需要这些数据。我不想弄清楚Action究竟做了什么,只想简单地执行()它并获取数据。我尝试这样做的方式是通过运行一个测试来执行()Action。

我的struts.xml不是直接在我正在构建的项目中。我的情况是这样的:我们把我的新项目称为项目A;以及我所依赖的传统struts项目,项目B。项目A是由其他框架(JSF;春天)。项目B使用struts作为UI。但是它的action是以一种非常混乱的方式编写的,以至于很多DB访问逻辑都是直接在action中编写的。因此,如果我想使用项目B的逻辑,而不是重写它,一个临时的解决方案(这是我试图完成的)将是从项目B执行一个Action与相应的请求数据。要做到这一点,方法是在a的服务类中对B的Action运行测试。

由于项目B被打包为war文件,我在项目a中与Maven一起重用它的方法是将其定义为项目a中的覆盖。项目B的类路径中的类和其他资源被打包到一个jar中。然后在项目A中,我依赖于那个罐子。因此,struts.xml保存在包含项目b的类和xml的jar中。在编译时,项目A只能在项目A的jar中看到struts.xml。

只有当我打包项目A时,war B被解包,其内容(包括struts.xml)被复制到项目A的目标文件夹中,然后A + B被打包为war。(在final war中,struts.xml将同时存在于jar B和WEB-INF/类中。

所以在实践中,如果我尝试通过右键单击测试并"作为junit运行"来运行测试,它应该不会在我的类路径上的一些WEB-INF/类中找到struts.xml -首先,在我的工作空间中没有这样的东西,只有在创建的war中。其次,我只尝试在战争中运行测试(如上所示)。当时有WEB-INF/classes/struts.xml,为什么找不到?

先创建StrutsSpringObjectFactory实例,然后再创建Dispatcher实例。

final StrutsSpringObjectFactory ssf = new StrutsSpringObjectFactory("auto",
      "true", "false", servletContext, "false", dispatcher.getContainer());

但是看看Struts2 -junit-plugin来测试Struts2的动作。它有StrutsSpringJUnit4TestCase方便的方法,所以你不需要自己做所有的东西。

你需要包含Struts2-Spring-plugin(*.jar)

http://struts.apache.org/release/2.3.x/docs/spring-plugin.html

Spring Plugin通过重写Struts的ObjectFactory来工作增强核心框架对象的创建。当一个对象是创建时,它使用Struts配置中的class属性来对应于Spring配置中的id属性。如果不是找到后,将尝试像往常一样创建类,然后由春天。在action的情况下,Spring 2的bean作用域特性可以是用于将Action实例限定为会话、应用程序或对象自定义范围,在默认范围之上提供高级自定义每个请求范围。

相关内容

  • 没有找到相关文章