Announcement Announcement Module
Collapse
No announcement yet.
Accessing ApplicationContext / Beanfactory Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Accessing ApplicationContext / Beanfactory

    Hi,

    my question can be nearly summarized by this thread: http://forum.springframework.org/showthread.php?t=27884

    What we need to do is to get a bean which cannot be injected since the class is instantiated by a 3rd party tool. Therefore we need to have a BeanFactory. Since we don't want to create a new BeanFactory by writing

    Code:
    BeanFactory bf = new ClassPathXmlApplicationContext("applicationContext.xml");
    bf.getBean("userDAO");
    But one ApplicationContext is created in a tomcat application server:

    Code:
    <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    
    <listener>
      <listener-class>
         org.springframework.web.context.ContextLoaderListener
       </listener-class>
    </listener>
    
    <servlet>
      <servlet-name>jobs</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>/WEB-INF/applicationContext.xml</param-value>
        </init-param>			
      <load-on-startup>1</load-on-startup>
    </servlet>
    How can I access the BeanFactory, which is only _once_ created?
    Last edited by sneumi; Jun 13th, 2007, 08:40 AM.

  • #2
    What we need to do is to get a bean which cannot be injected since the class is instantiated by a 3rd party tool.
    I'm not sure what you mean by that. How are you normally supposed to get this class created by this third party tool? What tool is it?

    Comment


    • #3
      Originally posted by cwilkes View Post
      I'm not sure what you mean by that. How are you normally supposed to get this class created by this third party tool? What tool is it?
      We have several 3rd party tools, which just remember the class and instantiate these by themself.

      eg.:

      * Hibernate Validator

      We need to write an validator, which access the database to validate a unique username.

      * Quartz

      (I guess you know) Jobs, which write data into the database.

      Comment


      • #4
        Let the Spring configured class which needs access to the ApplicationCOntext implement the ApplicationContextAware interface, the context will be automatically injected.

        Comment


        • #5
          Originally posted by mdeinum View Post
          Let the Spring configured class which needs access to the ApplicationCOntext implement the ApplicationContextAware interface, the context will be automatically injected.
          The thing is, the class is not spring configured. It is just a class, which will be instantiated by a 3rd party tool, but still needs to access a DAO.

          But still, the ApplicationContextAware is a quite useful hint. What my Solution would be:

          Code:
          public class BeanFactoryAccessor implements ApplicationContextAware , InitializingBean{
          	
          	private static final Log LOG = LogFactory.getLog(BeanFactoryAccessor.class);
          	
          	private static BeanFactory _ctx = null;
          	
          	public BeanFactoryAccessor() {
          		LOG.info("Creating BeanFactoryAccessor...");
          	}
          
          	public static BeanFactory getBeanFactory() {
          		if (_ctx==null){
          			BeanFactory bf = new ClassPathXmlApplicationContext("applicationContext.xml");
          			bf.getBean("userDAO");
          			LOG.fatal("Have no beanfactoy.... something must be wrong here");
          			throw new RuntimeException("Have no beanfactoy.... something must be wrong here");
          		}
          		return _ctx;
          	}
          
          	/* (non-Javadoc)
          	 * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
          	 */
          	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
          		LOG.info("Setting required ApplicationContext...");
          		_ctx=applicationContext;
          	}
          
          	/* (non-Javadoc)
          	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
          	 */
          	public void afterPropertiesSet() throws Exception {
          		Assert.notNull(_ctx);
          	}
          
          }
          So now, I could do something like:

          Code:
          UserDAO userDAO = (UserDAO) BeanFactoryAccessor.getBeanFactory().getBean("userDAO");
          What do think abaout that?

          Comment


          • #6
            No that won't work, you'll be creating another instance of the ApplicationContext. If you look back at the original thread, there was already a good way of solving it!
            Last edited by karldmoore; Aug 30th, 2007, 05:36 AM.

            Comment


            • #7
              For the quartz problem, there would be this solution:

              http://forum.springframework.org/arc...p/t-22499.html

              In case of the hibernate validation, I only see the BeaFactorySolution ....

              Comment


              • #8
                Ehhhh? I was talking about the BeanFactoryLocator option.
                http://forum.springframework.org/showthread.php?t=27884
                Last edited by karldmoore; Aug 30th, 2007, 05:36 AM.

                Comment


                • #9
                  Why Do I create a new ApplicationContext? I thought, that an ApplicationContextAware bean is getting the current ApplicationContext, and not a new one....

                  in the othe case, I can't see, why spring won't create a new ApllicationContext, since Spring gets this
                  Code:
                   
                  <beans>
                     <bean id="mainApplicationContext" lazy-init="true" class="org.springframework.context.support.ClassPathXmlApplicationContext">
                        <constructor-arg>
                           <value>myApplicationContext.xml</value>
                        </constructor-arg>
                     </bean>
                  </beans>
                  I would say, if the bean configuration above is in myApplicationContext.xml, than Spring won't recognize, that it creates new ApplicationContext, so we have at least two ApplicationContexts with the configuration myApplicationContext.xml.

                  In the ApplicationContextAware method, I would guess, that Spring recognize durring creation of the Bean, that the Bean wants to have the current ApplicationContext and give it to the bean, so only _one_ context?

                  Am I thinking in the wrong direction?

                  Comment


                  • #10
                    Summarize because a bit confusing:

                    Solutions

                    1) http://forum.springframework.org/showthread.php?t=27884

                    But I guess, it would create 2 ApplicationContexts

                    2) http://forum.springframework.org/sho...27&postcount=5

                    (In this thread above, the BeanFactoryAccessor solution)
                    I would guess, only one ApplicationContext is created

                    3) http://forum.springframework.org/arc...p/t-22499.html
                    not a real solution, but it would help for quartz since the jobs, that were created by quartz can be replaced by an own solution, which can access the ApllicationContext.

                    I hope, I made the point a bit clearer

                    Comment


                    • #11
                      Implementing ApplicationContextAware will give that bean access to the applicationContext. The code I was referring to was.
                      Code:
                      BeanFactory bf = new ClassPathXmlApplicationContext("applicationContext.xml");
                      Last edited by karldmoore; Aug 30th, 2007, 05:36 AM.

                      Comment


                      • #12
                        OK, thanks, but do I see it correctly that solution 1) would create a second ApplicationContext as well?

                        Comment


                        • #13
                          If you mean using SingletonBeanFactoryLocator or ContextSingletonBeanFactoryLocator then no. I'd have a read of the JavaDoc and the reference manual for some more background information. Everything you need is on the original post. Likewise if you modify the code you posted it would work, it's just the former might be a cleaner solution.
                          Code:
                          	public static BeanFactory getBeanFactory() {
                          		if (_ctx==null){
                          			LOG.fatal("Have no beanfactoy.... something must be wrong here");
                          			throw new RuntimeException("Have no beanfactoy.... something must be wrong here");
                          		}
                          		return _ctx;
                          	}
                          Last edited by karldmoore; Aug 30th, 2007, 05:36 AM.

                          Comment


                          • #14
                            Just wondering wouldn't it possible to create a FactoryBean which wraps your third party tool? That way you could inject your objects instead of looking them up each time.

                            Comment


                            • #15
                              Originally posted by karldmoore View Post
                              If you mean using SingletonBeanFactoryLocator or ContextSingletonBeanFactoryLocator then no. I'd have a read of the JavaDoc and the reference manual for some more background information.
                              I disagree (but still not sure). Of course, if you use SingletonBeanFactoryLocator, it would use only one ApplicationContext, but the instance of ApplicationContext this Locator is using must be a duplicate.

                              like:

                              applicationContext.xml:

                              Code:
                                 <bean id="mainApplicationContext" lazy-init="true" class="org.springframework.context.support.ClassPathXmlApplicationContext">
                                    <constructor-arg>
                                       <value>applicationContext.xml</value>
                                    </constructor-arg>
                                 </bean>
                              </beans>
                              Ahhhh,... and a kind of proof is the lazy-init="true" because otherwise you would have and endless loop

                              Ok, got it.

                              Comment

                              Working...
                              X