2013-04-04 4 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

(Как примечание стороны, мне нужен этот код для того, чтобы иметь возможность моделировать работы распорок действия от моего унаследованного проекта, в системе, основывается на различных рамок)

у меня есть проблема со следующим пунктом:.

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

на втором литий пе, я получаю сообщение об ошибке: The method setObjectFactory(StrutsSpringObjectFactory) is undefined for the type ObjectFactory

Однако, когда я смотрю на javadoc of ObjectFactory, я не вижу, альтернативный метод, который позволил бы мне установить конкретный ObjectFactory (например, StrutsSpringObjectFactory), как ObjectFactory, который будет использоваться при выполнении действий. Итак, как мне установить такой конкретный ObjectFactory с новым API?

Обновленный код:

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()); 

} 

Стек след, который я получаю от этого кода, при вызове теста из в веб-приложение (развернутый войны):

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 

UPDATE 2:

Причина, по которой я хочу протестировать действие, - это не просто щелкнуть правой кнопкой мыши o n из проводника проекта, а затем щелкните правой кнопкой мыши «запустить как Junit». Я действительно хочу запустить тест как часть моего веб-приложения.

Это то, что я имею в виду: я пытаюсь вызвать следующий код одного из моих классов обслуживания:

DataTest test = new DataTest("testDataAction"); 

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

Потому что, в DataTest я пытаюсь выполнить() DataAction. Это действие вызывает некоторую беспорядочную логику db и в конечном итоге возвращает некоторые данные. Мне нужны эти данные для моего сервиса. Вместо того, чтобы пытаться выяснить, что делает действие, я просто хочу выполнить() его и получить данные. Способ, которым я пытаюсь это сделать, - запустить тест, который будет выполнять() действие.

Мои struts.xml не находятся непосредственно в проекте, который я создаю. Вот моя ситуация: позвольте мне назвать мой новый проект, проект A; и проект устаревших распорок, от которого я зависим, проект B. Проект A строится другой структурой (JSF & Spring). Проект B использует стойки для пользовательского интерфейса. Но его действия были написаны таким грязным способом, что большая часть логики доступа к БД была написана непосредственно в действиях. Поэтому, если я хочу использовать логику из проекта B и не переписывать ее, временным решением (которое я пытаюсь выполнить) было бы выполнение Action из проекта B с соответствующими данными запроса. Способ сделать это, выполнив тест на действие из B, в классе обслуживания от A.

Поскольку проект B был упакован как файл войны, мой способ повторно использовать его с Maven в проекте A, заключается в том, чтобы определить его как наложение в проекте A. Классы и другие ресурсы из класса path проекта B упакованы в банку. Тогда в проекте А у меня есть зависимость от этой банки. Так struts.xml живет в банке, которая содержит классы и xml проекта B. Во время компиляции проект A может видеть только struts.xml в банке проекта A.

Только когда я собираю проект A, войну B распаковывается, его содержимое (включая struts.xml) копируется в целевую папку проекта A, а затем A + B упаковываются вместе в качестве войны. (в финальной войне struts.xml будет как в банке B, так и в WEB-INF/классах с окончательной войной.

Итак, на практике, если я попытаюсь запустить тест, щелкнув правой кнопкой мыши test и их «запускать как junit», он не должен искать struts.xml в некоторых WEB-INF/классах в моем пути к классам - сначала в моей рабочей области нет такой вещи, только в созданной войне. Во-вторых, я пытаюсь запустить тест только с в течение войны (как я показал выше). В то время существует WEB-INF/classes/struts.xml, почему его не найти?

+0

Посмотрите на плагин struts2-junit и класс 'StrutsSpringJUnit4TestCase'. –

ответ

1

Просто создайте новый экземпляр StrutsSpringObjectFactory, но сделайте это после создания Dispatcher.

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

НО посмотрите на struts2-junit-плагин для тестирования действий Struts2. Он имеет StrutsSpringJUnit4TestCase с удобными методами, поэтому вам не нужно делать все это самостоятельно.

+0

Спасибо за подсказку в плагине, я обязательно попробую это, так как прочитав его документацию, похоже, что он соответствует моему делу. Однако с исходным кодом, который в ссылке, которую я привел в свой пост, после вашего исправления, он теперь компилируется, но я получаю ошибку (при запуске теста изнутри webapp): 'java.io.FileNotFoundException: не удалось открыть ресурс ServletContext [/WEB-INF/classes/struts.xml] '. Я проверил в той войне, которую я развернул, что struts.xml находится в этом месте относительно корня войны. И префиксная косая черта говорит мне, что Spring пытается выполнить поиск из корня. Почему это терпит неудачу? – rapt

+0

Кроме того, я просто попробовал плагин struts2-junit. Когда я пытаюсь переопределить 'protected String getConfigPath()', как в примере, я получаю ошибку компиляции 'Метод getConfigPath() типа TestAccountActionUsingStrutsTestCase должен переопределять или реализовывать метод супертипа' ... это работает для тебя? Я использую struts2-junit-plugin 2.3.8 в моем пом. – rapt

+0

Что вы подразумеваете под webapp? Где ваш файл struts.xml в вашем проекте (а не в развернутом webapp)? –

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) в ссылке, которую вы цитируете, говорят, что добавить '' to 'struts.xml' Если я использую несколько объектов - насколько я вижу, приведенный выше код использует только один. Я что-то пропустил? 2) в моем комментарии к Александру М, я говорю, что получаю исключение, что 'struts.xml' не может быть найден. Я думаю, он должен быть найден, прежде чем я пойду и отредактирую его. Как заставить его найти? – rapt