Announcement Announcement Module
Collapse
No announcement yet.
How best to set parent context bean into child context bean in this situation? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How best to set parent context bean into child context bean in this situation?

    Does anyone know how I can ensure that (1) a bean defined in the parent webapp context is set on the controller bean in the child portlet context and that (2) the controller bean has been fully configured such that I could call a method on the bean defined in the parent webapp context from the controller in afterPropertiesSet()?

    I have a simple task scheduling and in-memory result caching library ( http://garysweaver.github.com/nerot/ ) that allows the user to call methods on an instance of the class to schedule new tasks, then later I call methods to get the cached result of that class.

    I define the caching library config as a resource that lives in its jar as nerot/nerot.xml:

    Code:
    <?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:p="http://www.springframework.org/schema/p"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="
                http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
           >
    
        <context:annotation-config />
    
        <bean name="nerotScheduleFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
            <property name="waitForJobsToCompleteOnShutdown" value="false"/>
        </bean>
    
        <bean name="nerotStore" class="nerot.store.MemoryStore"/>
    
        <bean name="nerot" class="nerot.Nerot">
            <property name="scheduler" ref="nerotScheduleFactory"/>
            <property name="store" ref="nerotStore"/>
        </bean>
    </beans>
    Then in a portlet, I load that context into the root webapp context in web.xml:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
            "http://java.sun.com/dtd/web-app_2_3.dtd">
    <web-app>
        <display-name>My Portlet</display-name>
        <description>This is my portlet</description>
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <!-- the root context loaded when the webapp loads -->
            <param-value>
                /WEB-INF/context/myPortletContext.xml
                classpath*:nerot/nerot.xml
            </param-value>
        </context-param>
        <context-param>
            <param-name>webAppRootKey</param-name>
            <param-value>com.acme.MyPortlet</param-value>
        </context-param>
        <listener>
            <listener-class>org.springframework.web.util.WebAppRootListener</listener-class>
        </listener>
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        <servlet>
            <servlet-name>ViewRendererServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.ViewRendererServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>ViewRendererServlet</servlet-name>
            <url-pattern>/WEB-INF/servlet/view</url-pattern>
        </servlet-mapping>
    </web-app>
    (Note: this is config before Pluto modification.)

    The caching library beans get loaded into the root webapp context when the webapp is instantiated.

    However, I want to call a method on the caching library bean that I need access to within the portlet's context. Preferably, I'd like to do this in such a way that the portlet's context has been loaded first (in order to get parameters set on the controller), and then call the instance of the bean in the root webapp context with those parameters.

    I was hoping to use:

    Code:
    @Autowired
    private Nerot nerot;
    in the controller class.

    My previous implementation used:
    Code:
    // expecting feedUrl and intervalInMillis to have been set on the controller bean via Spring portlet context config
    public void afterPropertiesSet() throws Exception {
        nerot.scheduleRss(feedUrl, intervalInMillis);
    }
    in the controller (in the child context) to call the method I wanted to call in the "nerot" bean in the parent context.

    However, I'm having to rely on these config parameters to be set and the "nerot" bean instance to be set on the child context controller bean, before calling the schedule method.

    Maybe it is somehow as easy as referencing the root context's bean "nerot" from the child portlet context's bean config. What is the best way of doing that?

    (Please note that I'm calling schedule via a method like this instead of just configuring Quartz in Spring, because in other places I need schedule to be called at runtime. I realize care would need to be taken with that, since it is spawning new threads, and I don't want it to spawn too many. The reason I'm not using traditional caching is to avoid issues that we had with the application in requests getting delayed when an RSS feed was down. A more scalable solution that would persist the feed would be better, but I wanted something simple to use. In at least a few ways, I'm replicating and hiding some of the functionality already in Quartz.)
    Last edited by garysweaver; Oct 21st, 2010, 03:04 PM.

  • #2
    Problem was in the tests not loading parent context configurations

    I was thinking that it wasn't able to access the parent context bean, but the issue was that I wasn't loading the parent context config files as part of the tests. Here is an example of a working test after the fix:

    Code:
    package com.acme;
    
    import com.acme.MyController;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {
    "file:src/main/webapp/WEB-INF/context/myportletContext.xml",
    "classpath*:nerot/nerot.xml",
    "file:src/main/webapp/WEB-INF/context/portlet/myportlet.xml"})
    public class MyPortletControllerTest extends AbstractDependencyInjectionSpringContextTests {
    
        @Autowired
        public MyPortletController myPortletController;
    
        @Test
        public void testContextLoadsProperly() {
            assertNotNull(myPortletController.getNerot());
        }
    
        ...
    }
    (Note: I'm now realizing that the goal was to call the method when the root context initialized, and I shouldn't be configuring that in the controller, because then it delays the controller load while it does the first schedule call, so I'll need to do the schedule call via another bean that I'll configure in the root context. Should work, but I'll bet there is a better solution. Edit: I implemented classes that call schedule methods as soon as the bean properties are all set in v3.4 of Nerot.)
    Last edited by garysweaver; Oct 22nd, 2010, 01:48 PM.

    Comment


    • #3
      Thanks sharing. It's geat

      ___________________
      watch movies online

      Comment


      • #4
        Thanks!

        David,

        Glad to know this could be of use!

        Gary

        Comment

        Working...
        X