Announcement Announcement Module
Collapse
No announcement yet.
Prevent WebApplicationContext parent from being referenced by JobLauncher Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Prevent WebApplicationContext parent from being referenced by JobLauncher

    I'm launching batch jobs via an SimpleAsyncTaskExecutor from within a WebApplicationContext. The web application and the batch application share a number of beans, each of which are prototype scoped.

    The shared beans are autowired with beans that in the web context are scoped request or session.

    I have created a factory that detects the current ApplicationContext and returns a non-web scoped bean when the current context is not an application context, however I'd misread or misinterpreted the documentation stating that the jobs run in the own ApplicationContext which doesn't seem to be entirely true as each job's context still references the parent context.

    Jobs fail when executed because they appear to be retrieving the web scoped bean from the parent context, but there's no request scope on the batch thread.

    Code:
    public class RequestContextFactory implements ApplicationContextAware
    {
        private boolean _webContextAvailable;
        private ApplicationContext _applicationContext;
    
        @Bean( name = "RequestContext" )
        @Primary
        public RequestContext getRequestContext()
        {
            if ( _webContextAvailable )
            {
                return ( RequestContext ) _applicationContext.getBean( "WebRequestContext" );
            }
            return ( RequestContext ) _applicationContext.getBean( "BatchRequestContext" );
    
        }
    
        @Override
        public void setApplicationContext( ApplicationContext applicationContext )
        {
            _applicationContext = applicationContext;
            _webContextAvailable = applicationContext instanceof WebApplicationContext;
        }
    }
    
    @Component( "WebRequestContext" )
    @Scope( value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS )
    public class RequestContext
    {
        // stuff
    }
    
    @Component( "BatchRequestContext" )
    @Scope( BeanDefinition.SCOPE_PROTOTYPE )
    public class BatchRequestContext extends RequestContext
    {
        // stuff
    }
    Jobs are registered using the AutomaticJobRegistrar, and I've attempted to configure the jobRegistry both with, and without a separate ApplicationContextJobFactory to create a ClassPathXmlApplicationContextFactory that is completely separate from the surrounding WebApplicationContext.

    HTML Code:
    <bean class="org.springframework.batch.core.configuration.support.AutomaticJobRegistrar">
       <property name="applicationContextFactories">
          <bean class="org.springframework.batch.core.configuration.support.ClasspathXmlApplicationContextsFactoryBean">
             <property name="resources" value="classpath*:/batch-jobs/*-job.xml" />         
          </bean>
       </property>
       <property name="jobLoader">
          <bean class="org.springframework.batch.core.configuration.support.DefaultJobLoader">
             <property name="jobRegistry" ref="jobRegistry" />
          </bean>
       </property>
    </bean>  
    
    <bean id="jobRegistry" class="org.springframework.batch.core.configuration.support.MapJobRegistry" />
    How do I create a completely separate (i.e. no references back to the parent WebApplicationContext) parent context for batch jobs so that my factory is invoked again, or is there a better way of achieving what I need?
Working...
X