Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: ApplicationContext in Ant Task.

  1. #1
    Join Date
    May 2005
    Posts
    17

    Default ApplicationContext in Ant Task.

    I am trying to create an ApplicationContext (specifically a FileSystemXmlApplicationContext) in a custom Ant task I have written. It finds the XML file correctly, and then throws NoClassDefFoundException for a bean that is the DriverManagerDataSource....
    Right before I init the context I can call Class.forName() for the driver manager class and it loads fine, so why won't the bean factory find it?
    what classpath concept am I missing? I have pored through my Spring in Action book and these forums and still haven't a solution.
    Any help would be greatly appreciated.

  2. #2
    Join Date
    Aug 2004
    Location
    u.s.a
    Posts
    399

    Default Re: ApplicationContext in Ant Task.

    Quote Originally Posted by stibrian
    I am trying to create an ApplicationContext (specifically a FileSystemXmlApplicationContext) in a custom Ant task I have written. It finds the XML file correctly, and then throws NoClassDefFoundException for a bean that is the DriverManagerDataSource....
    Right before I init the context I can call Class.forName() for the driver manager class and it loads fine, so why won't the bean factory find it?
    what classpath concept am I missing? I have pored through my Spring in Action book and these forums and still haven't a solution.
    Any help would be greatly appreciated.
    Did my article on integrating Spring into Ant help in any way?
    See: http://www.javaworld.com/javaworld/j...antspring.html

  3. #3
    Join Date
    May 2005
    Posts
    17

    Default Useful article

    The article is nice, and I'm going to look at using your technique in the future (maybe this time if I keep having issues). I am actually working towards something much simpler though.
    My Task:
    Code:
    private void setupBeanFactory() throws BeansException, FileNotFoundException, ClassNotFoundException{
            
            Class.forName("org.springframework.jdbc.datasource.DriverManagerDataSource");
            
            FileSystemXmlApplicationContext cp2 = new     FileSystemXmlApplicationContext("etc/config/config.xml");
          }
        
        /** 
         * The main point of entry when ant calls our custom task.
         */
        public void execute() throws BuildException {
            try {
                setupBeanFactory();
            } catch (Exception e) {
                            e.printStackTrace();
            }
        }
    My config.xml:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http&#58;//www.springframework.org/dtd/spring-beans.dtd">
    <beans>
        <!--  our jndi datasource -->
    	<bean id="dataSource"
    		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    		<property name="url">
    			<value>jdbc&#58;mysql&#58;//localhost/dbName?autoReconnect=true</value>
    		</property>
    		<property name="username">
    			<value>password</value>
    		</property>
    		<property name="password">
    			<value>password</value>
    		</property>
    		<property name="driverClassName">
    			<value>org.gjt.mm.mysql.Driver</value>
    		</property>
    	</bean>
    
    	<!--  create the session factory with the correct dialect with our datasource -->
    	<bean id="sessionFactory"
    		class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
    		<property name="dataSource">
    			<ref bean="dataSource" />
    		</property>
    		<property name="hibernateProperties">
    			<props>
    				<prop key="hibernate.dialect">
    					net.sf.hibernate.dialect.MySQLDialect
    				</prop>
    			  <!-- <prop key="hibernate.show_sql">
    			  	true
    			  </prop>-->
    			</props>
    		</property>
    		<property name="mappingDirectoryLocations">
    			<list>
    				<value>classpath&#58;my class mappings directory</value>
    			</list>
    		</property>
    	</bean>
    
    	<!--  create the hibernate template based on our session factory -->
    	<bean id="hibernateTemplate"
    		class="org.springframework.orm.hibernate.HibernateTemplate">
    		<property name="sessionFactory">
    			<ref bean="sessionFactory" />
    		</property>
    	</bean>
    	
    	
    	
    </beans>
    Now when Ant executes I get this stack trace:
    Code:
    &#91;exportDomainData&#93; &#40;xml.XmlBeanDefinitionReader         119 &#41; Loading XML bean definitions from file &#91;C&#58;\java\eclipse\workspace\hit\etc\config\config.xml&#93;
    &#91;exportDomainData&#93; org.springframework.beans.factory.BeanDefinitionStoreException&#58; Error registering bean with name 'dataSource' defined in file &#91;C&#58;\java\eclipse\workspace\hit\etc\config\config.xml&#93;&#58; Bean class &#91;org.springframework.jdbc.datasource.DriverManagerDataSource&#93; not found; nested exception is java.lang.ClassNotFoundException&#58; org.springframework.jdbc.datasource.DriverManagerDataSource
    &#91;exportDomainData&#93; java.lang.ClassNotFoundException&#58; org.springframework.jdbc.datasource.DriverManagerDataSource
    &#91;exportDomainData&#93; at java.net.URLClassLoader$1.run&#40;URLClassLoader.java&#58;199&#41;
    &#91;exportDomainData&#93; at java.security.AccessController.doPrivileged&#40;Native Method&#41;
    &#91;exportDomainData&#93; at java.net.URLClassLoader.findClass&#40;URLClassLoader.java&#58;187&#41;
    &#91;exportDomainData&#93; at java.lang.ClassLoader.loadClass&#40;ClassLoader.java&#58;289&#41;
    &#91;exportDomainData&#93; at sun.misc.Launcher$AppClassLoader.loadClass&#40;Launcher.java&#58;274&#41;
    &#91;exportDomainData&#93; at java.lang.ClassLoader.loadClass&#40;ClassLoader.java&#58;235&#41;
    &#91;exportDomainData&#93; at java.lang.ClassLoader.loadClassInternal&#40;ClassLoader.java&#58;302&#41;
    &#91;exportDomainData&#93; at java.lang.Class.forName0&#40;Native Method&#41;
    &#91;exportDomainData&#93; at java.lang.Class.forName&#40;Class.java&#58;219&#41;
    &#91;exportDomainData&#93; at org.springframework.beans.factory.support.BeanDefinitionReaderUtils.createBeanDefinition&#40;BeanDefinitionReaderUtils.java&#58;60&#41;
    &#91;exportDomainData&#93; at org.springframework.beans.factory.xml.DefaultXmlBeanDefinitionParser.parseBeanDefinition&#40;DefaultXmlBeanDefinitionParser.java&#58;306&#41;
    &#91;exportDomainData&#93; at org.springframework.beans.factory.xml.DefaultXmlBeanDefinitionParser.parseBeanDefinition&#40;DefaultXmlBeanDefinitionParser.java&#58;274&#41;
    &#91;exportDomainData&#93; at org.springframework.beans.factory.xml.DefaultXmlBeanDefinitionParser.registerBeanDefinitions&#40;DefaultXmlBeanDefinitionParser.java&#58;186&#41;
    &#91;exportDomainData&#93; at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions&#40;XmlBeanDefinitionReader.java&#58;175&#41;
    &#91;exportDomainData&#93; at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions&#40;XmlBeanDefinitionReader.java&#58;133&#41;
    &#91;exportDomainData&#93; at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions&#40;AbstractBeanDefinitionReader.java&#58;99&#41;
    &#91;exportDomainData&#93; at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions&#40;AbstractXmlApplicationContext.java&#58;102&#41;
    &#91;exportDomainData&#93; at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions&#40;AbstractXmlApplicationContext.java&#58;70&#41;
    &#91;exportDomainData&#93; at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory&#40;AbstractRefreshableApplicationContext.java&#58;87&#41;
    &#91;exportDomainData&#93; at org.springframework.context.support.AbstractApplicationContext.refresh&#40;AbstractApplicationContext.java&#58;262&#41;
    &#91;exportDomainData&#93; at org.springframework.context.support.FileSystemXmlApplicationContext.<init>&#40;FileSystemXmlApplicationContext.java&#58;82&#41;
    &#91;exportDomainData&#93; at org.springframework.context.support.FileSystemXmlApplicationContext.<init>&#40;FileSystemXmlApplicationContext.java&#58;67&#41;
    &#91;exportDomainData&#93; at org.springframework.context.support.FileSystemXmlApplicationContext.<init>&#40;FileSystemXmlApplicationContext.java&#58;58&#41;
    &#91;exportDomainData&#93; at com.sourceallies.hit.util.ant.DomainDataExportTask.setupBeanFactory&#40;Unknown Source&#41;
    &#91;exportDomainData&#93; at com.sourceallies.hit.util.ant.DomainDataExportTask.execute&#40;Unknown Source&#41;
    &#91;exportDomainData&#93; at org.apache.tools.ant.UnknownElement.execute&#40;UnknownElement.java&#58;275&#41;
    &#91;exportDomainData&#93; at org.apache.tools.ant.Task.perform&#40;Task.java&#58;364&#41;
    &#91;exportDomainData&#93; at org.apache.tools.ant.Target.execute&#40;Target.java&#58;341&#41;
    &#91;exportDomainData&#93; at org.apache.tools.ant.Target.performTasks&#40;Target.java&#58;369&#41;
    &#91;exportDomainData&#93; at org.apache.tools.ant.Project.executeTarget&#40;Project.java&#58;1214&#41;
    &#91;exportDomainData&#93; at org.apache.tools.ant.Project.executeTargets&#40;Project.java&#58;1062&#41;
    &#91;exportDomainData&#93; at org.eclipse.ant.internal.ui.antsupport.InternalAntRunner.run&#40;InternalAntRunner.java&#58;387&#41;
    &#91;exportDomainData&#93; at org.eclipse.ant.internal.ui.antsupport.InternalAntRunner.main&#40;InternalAntRunner.java&#58;136&#41;
    Note the call to Class.forName() that loads the same class right before I try to load the ApplicationContext. It succeeds, and you can see from the stack trace that my Spring configuration file is being propertly loaded and read, but barfs when trying to instantiate the DriverManager. Why?

    I'm a relative Spring newbie, and I'm pretty sure there's something fundamental I'm missing here, but what is it?

    BTW - nice article. I've bookmarked it for future use as I wish to do more Ant/Spring stuff, but this is a quick and dirty and I can't make that work.

    Why won't the FileSystemXmlApplicationContext load a class from the same classpath that the code on the preceding line is using?

    Thanks again for the help.

    Brian

  4. #4
    Join Date
    Aug 2004
    Location
    u.s.a
    Posts
    399

    Default

    I haven't looked closely at your stack traces (I'm at work right now), however, when working on the Ant project, I did run into class loader issues. The way Ant does classloader stuff does not allow straightforward reuse. I used a technique I found in the Ant mailing list. Not sure if this is applicable to your exact problem.

  5. #5
    Join Date
    May 2005
    Posts
    17

    Default ant classloader

    I'll look at your code more closely to see what you're talking about, but if it is an ant classloader issue then why can I load the class with Class.forName() but not with the ApplicationContext? I'm not a classloading genius so maybe I'm missing a subtlety here.... i'm rather confused.

  6. #6
    Join Date
    Oct 2004
    Location
    Herndon, VA, US
    Posts
    648

    Default

    Class.forName() uses the classloader that loaded the current class, while I think ApplicationContext's implementations use the current thread context classloader. That might be what caused the different behavior (not sure how exactly though).
    --Jing Xue

  7. #7
    Join Date
    May 2005
    Posts
    17

    Default

    I can't say as I understand the difference between the classloader that loaded the current class and the thread context classloader. I have a single thread of execution, why aren't they the same? As I said, I'm not a classloader guru, but am now more confused than ever.
    If these 2 classloaders are in fact different, this begs the question: how do I tell Spring to use the classload that loaded the class I'm CALLING SPRING FROM, rather than some other one. I don't see how that behavior would make sense, but I'm always looking to be schooled, or at least pointed in the right direction.

  8. #8
    Join Date
    Aug 2004
    Location
    u.s.a
    Posts
    399

    Default

    Classloader limitations are the floppy disk of the 21st century.

    In my Ant implementation's AbstractAntTask I have:

    Code:
            // code to handle cnf issues with taskdef classloader
            AntClassLoader2 antClassLoader = null;
            Object obj = this.getClass&#40;&#41;.getClassLoader&#40;&#41;;
            if &#40;obj instanceof AntClassLoader2&#41; &#123;
                antClassLoader = &#40;AntClassLoader2&#41; obj;
                antClassLoader.setThreadContextLoader&#40;&#41;;
            &#125;
            // end code to handle classnotfound issue
    But, my issue was that the unit tests would not run in both command line and Eclipse. Anyway, I'm not a classloader expert.

  9. #9
    Join Date
    Oct 2004
    Location
    Herndon, VA, US
    Posts
    648

    Default

    Quote Originally Posted by stibrian
    I can't say as I understand the difference between the classloader that loaded the current class and the thread context classloader. I have a single thread of execution, why aren't they the same? As I said, I'm not a classloader guru, but am now more confused than ever.
    I don't understand how exactly it didn't work either. Why don't you print out the class names of the two classloaders - even just for the sake of knowing?

    Quote Originally Posted by stibrian
    If these 2 classloaders are in fact different, this begs the question: how do I tell Spring to use the classload that loaded the class I'm CALLING SPRING FROM, rather than some other one. I don't see how that behavior would make sense, but I'm always looking to be schooled, or at least pointed in the right direction.
    Have you tried using setContextClassLoader as jbetancourt pointed out?
    --Jing Xue

  10. #10
    Join Date
    May 2005
    Posts
    17

    Default

    Having gotten a fix (thanks a million jbetancourt ), I plan to do more more investigation/education about classloaders in general. the code from teh abstract ant task that jbetancourt posted did the trick, but I hate to use even asnippet of code if I don't understand why its there - that's just prgramming by coincidence. :evil:

    Funny thing, this same snippet of code was used to modify the Jasperreports ant compiler task.... now I REALLY have to understand what's going on.

    Thanks for all the help, and I'll post any other information relevant to this topic here.

    Brian

Similar Threads

  1. problems loading applicationcontext
    By andrea_z in forum Web
    Replies: 6
    Last Post: Feb 8th, 2006, 08:25 AM
  2. Replies: 2
    Last Post: Oct 13th, 2005, 09:58 AM
  3. Replies: 4
    Last Post: Jun 8th, 2005, 06:22 AM
  4. Obtaining ApplicationContext for web and batch apps
    By Thomas Vaught in forum Container
    Replies: 10
    Last Post: May 23rd, 2005, 07:09 AM
  5. TransactionProxyFactory and ApplicationContext
    By newToSpring in forum Container
    Replies: 9
    Last Post: Oct 18th, 2004, 03:45 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
  •