我正在创建一个Spring MVC应用程序。
Controller依赖于服务层中的某个服务[name:TestExecutionOrchestratorService.java]。 TestExecutionOrchestratorService依赖于其他几项服务 [name:JUnitTestExecutorService,QTPTestExecutorService]。配置设置为在Map中注入这些服务。
Controller和TestExecutionOrchestratorService使用注释自动装配。 TestExecutionOrchestratorService及其依赖项使用XML配置进行连接。
Controller正在获取TestExecutionOrchestratorService的对象。 TestExecutionOrchestratorService正在获取 注入依赖服务的地图[我可以通过打印出的日志消息告诉]。我将此Map保存为实例 TestExecutionOrchestratorService中的变量。但是,TestExecutionOrchestratorService对象的实例 在依赖注入期间,Controller似乎没有设置Map。换句话说:
控制器--- DEPENDS ON ---> TestExecutionOrchestratorService --- DEPENDS ON ---> Map [of JUnitTestExecutorService,QTPTestExecutorService] 在Controller中设置的TestExecutionOrchestratorService实例中,Map为空。我从日志消息中知道了 在服务器启动期间注入了映射。
代码和XML文件如下:
/**
* Handles requests for the application home page.
*/
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
@Autowired
private TestExecutionOrchestratorService testExecutionOrchestratorService;
/**
* Simply selects the home view to render by returning its name.
*/
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! the client locale is "+ locale.toString());
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
//ISSUE: Call to the service layer. The Map in the service is empty even though dependency injection is happening
//there.
if (testExecutionOrchestratorService != null) {
logger.info("testExecutionOrchestratorService is not null. Executing it...");
testExecutionOrchestratorService.runTests();
}
else {
logger.info("testExecutionOrchestratorService is null. Why Why Why??");
}
return "home";
}
}
/*
* This class is the entry point into test execution. It takes the request to execute tests
* and calls the appropriate test executors.
*/
@Service("testExecutionOrchestratorService")
public class TestExecutionOrchestratorService implements TestResultsReporter {
/* List of executor services */
private Map<String, TestExecutorService> testExecutors = new HashMap<String, TestExecutorService>();
private static final Logger logger = LoggerFactory.getLogger(TestExecutionOrchestratorService.class);
/*
* For Spring's dependency injection - to inject all the test executors.
*/
public void setExecutormap(Map<String, TestExecutorService> exMap) {
if (exMap != null) {
Set<Entry<String, TestExecutorService>> mapEntrySet = exMap.entrySet();
logger.error("TestExecutionOrchestratorService [setExecutorMap]: Got a map of test executors. The entries are:");
for (Entry<String, TestExecutorService> mapE: mapEntrySet) {
logger.error("Key: " + mapE.getKey() + ", Value: " + mapE.getValue().getExecutorName());
}
//ISSUE: testExecutors is showing as null in the "runTests" method that is called by the Controller. Why??
testExecutors.putAll(exMap);
}
else {
logger.error("TestExecutionOrchestratorService [setExecutorMap]: Got a null executors map");
}
}
/* runTests - Calls upon the various executors to run the tests.
* ISSUE: The Controller is calling this method but the Map set in 'setExecutorMap' is not being found. */
public void runTests() {
logger.error("TestExecutionOrchestratorService [runTests]: Entering the method");
/* Create a unique test run ID. This will be the current time stamp. */
String testRunTimestamp = new Timestamp(new Date().getTime()).toString();
logger.error("TestExecutionOrchestratorService [runTests]: Will execute executors with test run ID: " + testRunTimestamp);
/* Call each executor and ask them to run their default tests. */
if ((testExecutors != null) && (!testExecutors.isEmpty())) {
logger.error("TestExecutionOrchestratorService [runTests]: test executors are available. Will execute them.");
Collection<TestExecutorService> teServices = testExecutors.values();
for (TestExecutorService teService: teServices) {
teService.runTests(testRunTimestamp, null, this);
}
}
else {
/* ISSUE: THIS IS WHERE EXECUTION IS ALWAYS COMING */
logger.error("TestExecutionOrchestratorService [runTests]: There are no test executors available.");
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="..">
<!-- Root Context: defines shared resources visible to all other web components -->
<!-- Defining services -->
<!-- The following services are defined here: TestExecutionOrchestratorService,
JUnitTestExecutorService, QTPTestExecutorService -->
<!-- Definition of the JUnitTestExecutorService -->
<bean id="junitexecutor" name="junitexecutor" class="com.testing.autofwk.execution.JUnitTestExecutorService" />
<!-- Definition of the QTPTestExecutorService -->
<bean id="qtpexecutor" name="qtpexecutor" class="com.testing.autofwk.execution.QTPTestExecutorService" />
<!-- Definition of the TestExecutionOrchestratorService -->
<bean id="testexecutororchestrator" name="testexecutororchestrator" class="com.testing.autofwk.execution.TestExecutionOrchestratorService">
<property name="executormap">
<map>
<entry key="junit">
<ref local="junitexecutor"/>
</entry>
<entry key="qtp">
<ref local="qtpexecutor"/>
</entry>
</map>
</property>
</bean>
<context:component-scan base-package="com.testing.autofwk.execution" />
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="..">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.testing.autofwk" />
</beans:beans>
答案 0 :(得分:2)
您似乎正在创建多个TestExecutionOrchestratorService
,并且在控制器中注入了错误的一个TestExecutionOrchestratorService
。加载root-context.xml时会创建一个对象,并且由于@Service
具有<context:component-scan base-package="com.testing.autofwk" use-default-filters="false">
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation" />
</context:component-scan>
注释,因此在类扫描时将创建其他bean。
最重要的是,由于调度程序的上下文XML文件,某些程序包将扫描两次。
最好在调度程序的上下文XML文件中使用类似的东西,以避免多次扫描同一个类:
<context:component-scan base-package="com.testing.autofwk">
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
在根文中:
{{1}}