Announcement Announcement Module
Collapse
No announcement yet.
Dependency Injection Issue (transitive) in Spring MVC app [version 3.1.0.RELEASE] Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Dependency Injection Issue (transitive) in Spring MVC app [version 3.1.0.RELEASE]

    I am creating a Spring MVC application.

    The Controller depends on one of the services [name: TestExecutionOrchestratorService.java] in the Service layer.
    The TestExecutionOrchestratorService depends on a couple of other services
    [names: JUnitTestExecutorService, QTPTestExecutorService].The configuration is set up to inject these services in a Map.

    The Controller and the TestExecutionOrchestratorService are autowired using annotations.
    The TestExecutionOrchestratorService and its dependencies are wired using XML configuration (using Map).

    Problem:
    -------
    The Controller is getting an object of TestExecutionOrchestratorService. The TestExecutionOrchestratorService is getting
    the Map of dependency services injected [I can tell by the log messages printed out]. I save this Map as an instance
    variable in the TestExecutionOrchestratorService. However, the instance of the TestExecutionOrchestratorService object in the
    Controller does not seem to have the Map set during dependency injection. In other words:

    Controller---DEPENDS ON--->TestExecutionOrchestratorService---DEPENDS ON--->Map[of JUnitTestExecutorService, QTPTestExecutorService]
    The Map is empty in the instance of the TestExecutionOrchestratorService set in the Controller. I know from log messages that the
    Map is being injected into the TestExecutionOrchestratorService during server startup.

    The code and XML files are below:

    Listing 1 - Controller
    ----------------------

    /**
    * 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 );

    //PROBLEM: 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";
    }

    }


    Listing 2 - TestExecutionOrchestratorService
    --------------------------------------------
    /*
    * 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(TestExecutionOrchestratorS ervice.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());
    }

    //PROBLEM: 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.
    * PROBLEM: 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 {
    /* PROBLEM: THIS IS WHERE EXECUTION IS ALWAYS COMING */
    logger.error("TestExecutionOrchestratorService [runTests]: There are no test executors available.");
    }

    }
    }



    Listing 3 - Spring's Web context XML file (root-context.xml)
    ------------------------------------------------------------
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schem...-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.1.xsd">


    <!-- 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.JUnitTestExec utorService" />
    <!-- Definition of the QTPTestExecutorService -->
    <bean id="qtpexecutor" name="qtpexecutor" class="com.testing.autofwk.execution.QTPTestExecut orService" />
    <!-- Definition of the TestExecutionOrchestratorService -->
    <bean id="testexecutororchestrator" name="testexecutororchestrator" class="com.testing.autofwk.execution.TestExecution OrchestratorService">
    <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>


    Listing 4 - The MVC application dispatcher's context XML file (servlet-context.xml)
    -----------------------------------------------------------------------------------
    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schem...ng-mvc-3.0.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schem...-beans-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- 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.Intern alResourceViewResolver">
    <beansroperty name="prefix" value="/WEB-INF/views/" />
    <beansroperty name="suffix" value=".jsp" />
    </beans:bean>

    <context:component-scan base-package="com.testing.autofwk" />



    </beans:beans>
Working...
X