Results 1 to 7 of 7

Thread: Loading context from custom classloader

  1. #1
    Join Date
    Sep 2005
    Posts
    21

    Default Loading context from custom classloader

    I have a Spring-based application distributed in one or more jar files. Context file(s) are packaged inside of the jars.

    I need to dynamically load the contexts defined there from another application at runtime. I constructed a UrlClassLoader using the jars and use this classloader to create new instance of ClasspathXmlApplicationContext:
    Code:
    		
    loader = getClassLoader();
    Class contextClass = Class.forName(ClassPathXmlApplicationContext.class
    				.getName(), true, loader);
    		Constructor constructor = contextClass
    				.getConstructor(new Class[] { String[].class });
    		context = (ClassPathXmlApplicationContext) constructor.newInstance(new Object[] { new String[] {
    "com/path/to/my/spring-context.xml"} } );
    The problem is that context cannot be found. It appears that ClasspathxmlApplicationContext does not even look at resources defined by my custom classloader.

    Spring documentation indicates that there is a setClassLoader method available in this type of context but in fact there is not one.

    How should I handle this situation?
    TIA

  2. #2
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    javadoc for : org.springframework.context.support.ClassPathXmlAp plicationContext
    Methods inherited from class org.springframework.core.io.DefaultResourceLoader
    getClassLoader, getResource, getResourceByPath, setClassLoader
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  3. #3
    Join Date
    Sep 2005
    Posts
    21

    Default

    yes I can read Javadoc, that is what I meant by "Spring Documentation" ;-)
    The DefaultResourceLoader does NOT have the setter method Javadoc says it does.

    Plus it would not help anyway because context object is already constructed.

  4. #4
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    the DefaultResourceLoader does NOT have the setter method Javadoc says it does.
    From my source code of Spring (1.2.4):

    Code:
    public class DefaultResourceLoader implements ResourceLoader {
    
    	private ClassLoader classLoader;
    
    
    	/**
    	 * Create a new DefaultResourceLoader.
    	 * <p>ClassLoader access will happen via the thread context class loader on actual
    	 * access &#40;applying to the thread that does ClassPathResource calls&#41;.
    	 * @see java.lang.Thread#getContextClassLoader&#40;&#41;
    	 */
    	public DefaultResourceLoader&#40;&#41; &#123;
    	&#125;
    
    	/**
    	 * Create a new DefaultResourceLoader.
    	 * @param classLoader the ClassLoader to load class path resources with,
    	 * or null if using the thread context class loader on actual access
    	 * &#40;applying to the thread that does ClassPathResource calls&#41;
    	 */
    	public DefaultResourceLoader&#40;ClassLoader classLoader&#41; &#123;
    		this.classLoader = classLoader;
    	&#125;
    
    
    	/**
    	 * Specify the ClassLoader to load class path resources with,
    	 * or null if using the thread context class loader on actual access
    	 * &#40;applying to the thread that does ClassPathResource calls&#41;.
    	 * <p>The default is that ClassLoader access will happen via the thread
    	 * context class loader on actual access &#40;applying to the thread that
    	 * does ClassPathResource calls&#41;.
    	 */
    	public void setClassLoader&#40;ClassLoader classLoader&#41; &#123;
    		this.classLoader = classLoader;
    	&#125;
    Look at the ClassPathXmlApplicationContext and it's ancesters code:
    (from AbstractXmlApplicationContext)
    Code:
       /**
    	 * Loads the bean definitions via an XmlBeanDefinitionReader.
    	 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
    	 * @see #initBeanDefinitionReader
    	 * @see #loadBeanDefinitions
    	 */
    	protected void loadBeanDefinitions&#40;DefaultListableBeanFactory beanFactory&#41; throws IOException &#123;
    ...
    		// Configure the bean definition reader with this context's
    
    		// resource loading environment.
    		beanDefinitionReader.setResourceLoader&#40;this&#41;;
    		if &#40;getClassLoader&#40;&#41; != null&#41; &#123;
    			beanDefinitionReader.setBeanClassLoader&#40;getClassLoader&#40;&#41;&#41;;
    		&#125;
    ...
    	&#125;
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  5. #5
    Join Date
    Sep 2005
    Posts
    21

    Default

    I am using 1.2.3 and it does not have that.

    Nevermind, because I figured it out. Spring apperantly uses the classloader context of the thread initiating the Spring context to find resources. So I just re-wrote my piece as:

    Code:
    		loader = getClassLoader&#40;&#41;;
    		Thread.currentThread&#40;&#41;.setContextClassLoader&#40;loader&#41;;
    		context = new ClassPathXmlApplicationContext&#40;new String&#91;&#93; &#123;
    "com/my/path/context.xml"
    				&#125;&#41;;
    and it works just fine.

    Thanks again, Spring developers, very elegant.

  6. #6
    Join Date
    May 2005
    Location
    San Francisco
    Posts
    61

    Default

    Code:
          loader = getClassLoader&#40;&#41;; 
          Thread.currentThread&#40;&#41;.setContextClassLoader&#40;loader&#41;; 
          context = new ClassPathXmlApplicationContext&#40;new String&#91;&#93; &#123; 
    "com/my/path/context.xml" 
                &#125;&#41;;
    and it works just fine.

    Thanks again, Spring developers, very elegant.
    It looks like setClassLoader() was added for this exactly (or related) tasks in the 1.2.4. It'd be probably much better to switch to 1.2.5 and use it. Playing with context classloader is rather dangerous and not portable. Besides having to worry about reinstating old TCCL you might also run into issues with security manager.

  7. #7
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    It looks like setClassLoader() was added for this exactly (or related) tasks in the 1.2.4. It'd be probably much better to switch to 1.2.5 and use it. Playing with context classloader is rather dangerous and not portable. Besides having to worry about reinstating old TCCL you might also run into issues with security manager.
    I second dvoytenko reply. It's better to use the official classloader setter (thus upgrading the spring library) then fool around with TCCL - especially inside a container (tomcat or a full AS) you might have some really wierd problems which are mainly caused by the CL.
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

Similar Threads

  1. Error loading context: unknown protocol: jndi
    By graeder in forum Container
    Replies: 12
    Last Post: Oct 27th, 2005, 09:07 AM
  2. Replies: 2
    Last Post: Oct 13th, 2005, 02:47 PM
  3. Loosing my SecureContext
    By sklakken in forum Security
    Replies: 3
    Last Post: Jul 21st, 2005, 01:44 PM
  4. Stack Overflow
    By rayho222 in forum Container
    Replies: 6
    Last Post: May 17th, 2005, 03:42 AM
  5. Single context loading for all test classes
    By thomasvdv in forum Container
    Replies: 13
    Last Post: Oct 6th, 2004, 03:32 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •