Announcement Announcement Module
Collapse
No announcement yet.
ClassLoader issue ! - Need Help Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • ClassLoader issue ! - Need Help

    Hi

    I am having problems in loading applicationContext.xml in an Eclipse Plugin.

    we are writing our application as an eclipse rcp Plugin and trying to use spring. If I use the spring in a standalone mode my backend works. But I am having problems only when i am using the spring inside an eclipse plugin.

    The folder that contains this file is in the plugin runtime directories.

    Here is the code I am using to load the application context file.

    Code:
    String[] paths = { "applicationContext.xml" };
    		ApplicationContext ctx = new ClassPathXmlApplicationContext(paths);
    Error:

    Feb 18, 2005 12:04:09 AM org.springframework.beans.factory.xml.XmlBeanDefin itionReader loadBeanDefinitions
    INFO: Loading XML bean definitions from class path resource [applicationContext.xml]
    org.springframework.beans.factory.BeanDefinitionSt oreException: IOException parsing XML document from class path resource [applicationContext.xml]; nested exception is java.io.FileNotFoundException: Could not open class path resource [applicationContext.xml]
    java.io.FileNotFoundException: Could not open class path resource [applicationContext.xml]
    at org.springframework.core.io.ClassPathResource.getI nputStream(ClassPathResource.java:109)
    at org.springframework.beans.factory.xml.XmlBeanDefin itionReader.loadBeanDefinitions(XmlBeanDefinitionR eader.java:129)
    at org.springframework.beans.factory.support.Abstract Bean

    If I load file as stream and pass to (see the code) below, it is loading the fiile but when it is creating the beans it is throwing class not found exception

    Code:
    URL url = ResourceManager.getPluginURL("config/applicationContext.xml");
    			
    beanFactory = new XmlBeanFactory(url.openStream());


    Code:
    applicationContext.xml 
    <beans>
       <bean id="mystring" class="java.lang.String"/>  &#58;-&#41; 
       <bean id="foo" class="com.mycode.core.Foo"/> &#58;-&#40;
       <bean id="bar" class="com.mycode.core.Bar"/> &#58;-&#40;
    </beans>
    The Foo and Bar classes are in my plugin class path.

  • #2
    Re: ClassLoader issue ?

    Originally posted by pkkishore
    Code:
    String&#91;&#93; paths = &#123; "applicationContext.xml" &#125;;
    ...
    URL url = ResourceManager.getPluginURL&#40;"config/applicationContext.xml"&#41;;
    The difference I see is, that in the working case you refer to "config/applicationContext.xml" whereas in the non-working case you just specify "applicationContext.xml".

    Maybe you just need to prepend the "config/". I think the "config" directory is not within your classpath, but its parent folder is. This would explain your problem.

    Regards,
    Andreas

    Comment


    • #3
      I suggest to do some simple tests by trying to load different files in your classpath. We have experienced the same problems when we started running a small stand-alone application under Eclipse - we just had to adjust some rules associated with building.
      If you'll be able to load the resources then so will the libraries.

      Comment


      • #4
        I have tried all the following combinations

        Code:
        String&#91;&#93; paths = &#123; "applicationContext.xml" &#125;;
        String&#91;&#93; paths = &#123; "/applicationContext.xml" &#125;;
        String&#91;&#93; paths = &#123; "config/applicationContext.xml" &#125;;
        String&#91;&#93; paths = &#123; "/config/applicationContext.xml" &#125;;
        But always I get a file not found exception.

        As I said in my standalone application, If I put
        Code:
        String&#91;&#93; paths = &#123; "applicationContext.xml" &#125;;
        the file is in config folder which is in my class path, it is working fine.

        I have to put "config/" for the file name in my resource manager. For example for loading images from my icons/ folder I am using the following code and it works.

        Code:
        ResourceManager.getPuginURL&#40;"icons/open.gif"&#41;;

        If I by pass spring and load Hibernate directly by using the following code I am able to load hibernate.cfg.xml


        Code:
        .......
        cfg.configure&#40;"/hibernate.cfg.xml"&#41;;
        both of these and other config files are in the same config/ folder.

        I tried loading log4j.xml using my resource manager by specifying

        Code:
        ResourceManager.getPuginURL&#40;"config/log4j.xml"&#41;;
        it loads correctly and DOMConfigurator is initialized.


        This is the standard method provided by SWTDesigner tool.
        Code:
        public static URL getPluginURL&#40;String relativePath&#41; throws Exception &#123;
        		Bundle bundle = Platform.getBundle&#40;"myapp"&#41;;
        
        		String newPath = relativePath;
        		if &#40;relativePath.length&#40;&#41; > 0 && relativePath.charAt&#40;0&#41; == '/'&#41;
        			newPath = relativePath.substring&#40;1, relativePath.length&#40;&#41;&#41;;
        		
        		Path path = new Path&#40;newPath&#41;;
        		URL fileURL = Platform.find&#40;bundle, path&#41;;
        		return fileURL;
        	&#125;

        Comment


        • #5
          In context to my first post, I tried the following also. (In my eclipse plugin code)

          I tried the following to use my resoure manager

          Code:
          URL url = ResourceManager.getPluginURL&#40;"config/applicationContext.xml"&#41;;
          			
          beanFactory = new XmlBeanFactory&#40;url.openStream&#40;&#41;&#41;;
          			
          Foo foo = &#40;Foo&#41;beanFactory.getBean&#40;"foo"&#41;;
          In this case, spring is reading the config file but, when it tries to instantiate it throws a class not found exception "com.mycode.core.Foo"
          It is able to load java.lang.String but not my application class Foo and Bar which are in class path.

          Code:
          applicationContext.xml
          <beans>
             <bean id="mystring" class="java.lang.String"/>  &#58;-&#41;
             <bean id="foo" class="com.mycode.core.Foo"/> &#58;-&#40;
             <bean id="bar" class="com.mycode.core.Bar"/> &#58;-&#40;
          </beans>

          Comment


          • #6
            My solution to enable use of ApplicationContext in Eclipse:

            Code:
            public class EclipseApplicationContext extends ClassPathXmlApplicationContext &#123;
                   ... 
                    copy of constructors here
                    ...
                    /** Return the current classLoader. */
            	public ClassLoader getClassLoader&#40;&#41; &#123;
            		return getClass&#40;&#41;.getClassLoader&#40;&#41;;
            	&#125;
            As far as I can tell Eclipse is playing weird tricks with the classpath. I am also having trouble (ClassNotFoundException) when loading classes via Spring inside an RCP Application. If anyone knows a solution I'd appriciate it; otherwise I will try and post one when I find it.

            Comment


            • #7
              Ok, add

              Code:
              protected void initBeanDefinitionReader&#40;XmlBeanDefinitionReader beanDefinitionReader&#41; &#123;
              		beanDefinitionReader.setBeanClassLoader&#40;getClassLoader&#40;&#41;&#41;;
              	&#125;
              to the code in my post above.

              Comment


              • #8
                Try to use a "dot" instead

                I have experience this in any classpath dependant application in Eclipse. And somehow they will load the path according to the package access in the classpath

                Example:

                original location in class path : config/applicationContext.xml
                change into: config.applicationContext.xml

                Hope it help

                Comment


                • #9
                  Make Spring use the right classloader.

                  Seems to me that Spring must be using the context classloader.

                  I found this in the Eclipse documentation:

                  -------------------- [Start: from Eclipse docs] ---------------------

                  FAQ 107 How do I use the context class loader in Eclipse?
                  In Java, each thread can optionally reference a context class loader. This loader can be set at any time by an application and is used for loading classes only when it is explicitly requested to do so. Many code libraries, in particular Java Database Connectivity (JDBC) and Xerces, use the context class loader in factory methods to allow clients of the library to specify what class loader to use. Although the context loader is not used by Eclipse itself, you may need to be aware of it when referencing third-party libraries from within Eclipse.

                  By default, the context loader is set to be the application class loader, which is not used in Eclipse. Because Eclipse has a separate class loader for each installed plug-in, a default class loader generally does not make sense as the context loader for a given thread. If you are calling third-party libraries that rely on the context loader, you will need to set it yourself. The following code snippet sets the context class loader before calling a library. Note that the code politely cleans up afterward by resetting the context loader to its original value:

                  Code:
                     Thread current = Thread.currentThread&#40;&#41;;
                     ClassLoader oldLoader = current.getContextClassLoader&#40;&#41;;
                     try &#123;
                        current.setContextClassLoader&#40;getClass&#40;&#41;.getClassLoader&#40;&#41;&#41;;
                        //call library code here
                     &#125; finally &#123;
                        current.setContextClassLoader&#40;oldLoader&#41;;
                     &#125;
                  -------------------- [End: from Eclipse docs] ---------------------

                  Therefore I am loading the ApplicationContext, and getting beans from it as follows:

                  Code:
                  ApplicationContext ctx;
                  SomeBean bean;
                  
                  Thread current = Thread.currentThread&#40;&#41;;
                  ClassLoader oldLoader = current.getContextClassLoader&#40;&#41;;
                  try &#123;
                      current.setContextClassLoader&#40;getClass&#40;&#41;.getClassLoader&#40;&#41;&#41;;
                      ctx = new ClassPathXmlApplicationContext&#40;"ApplicationContext.xml"&#41;;
                      bean = &#40;SomeBean&#41; ctx.getBean&#40;"someBean"&#41;;
                  &#125; finally &#123;
                     current.setContextClassLoader&#40;oldLoader&#41;;
                  &#125;
                  -- Claus

                  Comment


                  • #10
                    The code below works in an Eclipse plug-in.

                    Code:
                    ApplicationContext appCtx = new ClassPathXmlApplicationContext&#40;"applicationContext.xml"&#41; &#123;
                    			public ClassLoader getClassLoader&#40;&#41; &#123;
                    				return getClass&#40;&#41;.getClassLoader&#40;&#41;;
                    			&#125;
                    			
                    			protected void initBeanDefinitionReader&#40;org.springframework.beans.factory.xml.XmlBeanDefinitionReader reader&#41; &#123;
                    				super.initBeanDefinitionReader&#40;reader&#41;;
                    				reader.setBeanClassLoader&#40;getClassLoader&#40;&#41;&#41;;
                    			&#125;
                    		&#125;;

                    Comment


                    • #11
                      Classloading...

                      I was happy using this approach (overriding get loader und the reader init), until I remoted some beans.

                      Now I get the ClassNotFound problem again... Any idea on how to get around this problem?

                      brgds

                      Papick

                      Comment


                      • #12
                        That's a valid point. Standard Java deserialization uses the thread context loader. Spring could solve this issue but this hasn't happened so far. I've created a JIRA issue.

                        Comment

                        Working...
                        X