2013-04-04 37 views
1

我正在使用openSymphony 2.1.2和struts 2.3.8的项目。将StrutsSpringObjectFactory设置为我当前的ObjectFactory

但是,在那个代码库上,我试图应用一个为旧版本的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); 

在第二丽NE,我发现了错误:The method setObjectFactory(StrutsSpringObjectFactory) is undefined for the type ObjectFactory

然而,当我看着javadoc of ObjectFactory,我不认为这会让我设置一个替代方法的具体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应用程序(已部署的战争)内测试时:

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:

我希望能够测试一个动作的原因,不仅仅是为了能够右键单击o从项目浏览器中取出它,然后右键单击“以Junit身份运行”。我实际上想将测试作为我的Web应用程序的一部分运行。

这就是我的意思是:我想从我的服务类的一个调用下面的代码:

DataTest test = new DataTest("testDataAction"); 

JUnitCore jUnitCore = new JUnitCore(); 
jUnitCore.run(test); 

因为,在数据测试我尝试执行()DataAction。该Action调用一些凌乱的数据库逻辑并最终返回一些数据。我需要这些数据用于我的服务。我没有试图弄清楚Action究竟做了什么,而是简单地执行()它并获取数据。我试图做的方式是通过运行一个将执行()Action的测试。

我的struts.xml不直接在我正在构建的项目中。这是我的情况:让我们打电话给我的新项目,项目A;以及我依赖的传统struts项目,项目B. 项目A正在由其他框架(JSF & Spring)构建。 项目B使用struts作为UI。但是它的动作是以这样一种混乱的方式编写的,很多数据库访问逻辑是直接写在动作中的。所以,如果我想使用项目B中的逻辑,而不是重写它,那么临时解决方案(我试图完成的)就是从项目B执行一个具有相应请求数据的Action。 要做到这一点的方法是通过在A的服务类中对B中的Action执行测试。

由于项目B打包成一个war文件,我在项目A中用Maven重用它的方式是将其定义为项目A中的覆盖。012xx项目B的类路径中的类和其他资源已打包放入一个罐子里。然后在项目A中,我对该jar有依赖性。 因此,struts.xml驻留在包含项目B的类和xml的jar中。在编译时,项目A只能在项目A的jar中看到struts.xml。

只有当我打包项目A时, B被解压缩后,其内容(包括struts.xml)被复制到项目A的目标文件夹中,然后A + B作为war打包在一起。 (在最后的战争中,struts.xml将在jar B和WEB-INF/classes中进行最后的战争)。

所以实际上,如果我尝试通过右键单击测试和他们“作为junit运行”,它不应该在我的类路径中的某些WEB-INF /类中找到struts.xml - 首先,在我的工作空间中没有这样的事情,只有在创建的战争中;其次,我只尝试运行测试在一次战争中(如我上面所示),那时有WEB-INF/classes/struts.xml,为什么找不到它?

+0

看看struts2-junit插件和'StrutsSpringJUnit4TestCase'类。 – 2013-04-05 08:32:58

回答

1

只需创建StrutsSpringObjectFactory的新实例,但在创建Dispatcher之后执行此操作。

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

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

+0

感谢您的插件上的提示,我一定会尝试它,因为通过阅读它的文档,它看起来像它符合我的情况。但是,在链接中带入的原始代码中,在修复后,它现在编译,但出现错误(在webapp中运行测试时):java.io.FileNotFoundException:无法打开ServletContext资源[/WEB-INF/classes/struts.xml]'。我检查了我部署的那场战争,struts.xml位于相对于战争根源的位置。前缀斜杠告诉我,Spring试图从根进行搜索。它为什么会失败? – rapt 2013-04-05 12:33:21

+0

另外,我只是尝试了struts2-junit-plugin。当我尝试像在示例中那样重写'protected String getConfigPath()'时,我得到一个编译错误'TestAccountActionUsingStrutsTestCase类型的方法getConfigPath()必须覆盖或实现一个超类型方法....“为你?我在我的pom中使用了struts2-junit-plugin 2.3.8。 – rapt 2013-04-05 14:44:55

+0

在webapp中你是什么意思?项目中的struts.xml文件在哪里(不在部署的webapp中)? – 2013-04-05 17:08:45

0

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

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

The Spring Plugin works by overriding the Struts ObjectFactory to enhance the creation of core framework objects. When an object is to be created, it uses the class attribute in the Struts configuration to correspond to the id attribute in the Spring configuration. If not found, the class will try to be created as usual, then be autowired by Spring. In the case of Actions, Spring 2's bean scope feature can be used to scope an Action instance to the session, application, or a custom scope, providing advanced customization above the default per-request scoping.

+0

有两个问题:1)在你引用的链接中,他们说要将'<常量名=“struts.objectFactory”value =“spring”/>'添加到'struts.xml'中如果我使用多个对象工厂 - 就我所见,上面的代码只使用一个。我想念什么? 2)在对Aleksandr M的评论中,我说我得到一个例外,即找不到'struts.xml'。我认为应该在我去编辑它之前找到它。我如何使它找到? – rapt 2013-04-05 13:13:41

相关问题