Установка StrutsSpringObjectFactory как моей текущей ObjectFactory

Я работаю над проектом, который использует openSymphony 2.1.2 и стойки 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

Однако, когда я смотрю на javadoc 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://stackru.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

ОБНОВЛЕНИЕ 2:

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

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

DataTest test = new DataTest("testDataAction");

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

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

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

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

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

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

2 ответа

Решение

Просто создайте новый экземпляр 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 работает, переопределяя Struts ObjectFactory, чтобы улучшить создание базовых объектов каркаса. Когда объект должен быть создан, он использует атрибут класса в конфигурации Struts, чтобы соответствовать атрибуту id в конфигурации Spring. Если класс не найден, он будет пытаться создать его как обычно, а затем будет автоматически подключен к Spring. В случае Actions можно использовать функцию области действия bean-компонента Spring 2 для выделения экземпляра Action для сеанса, приложения или настраиваемой области, предоставляя расширенную настройку по сравнению с областью действия по умолчанию для каждого запроса.

Другие вопросы по тегам