Spring Framework
  1. Spring Framework
  2. SPR-9787

ServiceLoaderFactoryBean.beanClassLoader being incorrectly overwritten

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Won't Fix
    • Affects Version/s: 3.0.5
    • Fix Version/s: None
    • Component/s: Core
    • Labels:
      None

      Description

      Details are described in the forum. See reference url.

        Activity

        Hide
        Ben McDonie added a comment -

        I am having the EXACT same issue with ServiceListFactoryBean.

        The following is the hack/workaround that helped me get ServiceLoader using my custom class loader.

        MyServiceListFactoryBean.java
        public class MyServiceListFactoryBean extends ServiceListFactoryBean {
            private ClassLoader realClassLoader;
        
            public void setRealClassLoader(ClassLoader realClassLoader) {
                this.realClassLoader = realClassLoader;
            }
        
            @Override
            protected Object createInstance() {
                return getObjectToExpose(ServiceLoader.load(getServiceType(), this.realClassLoader));
            }
        }
        

        I basically just inject my custom class loader into this FactoryBean, and then override createInstance() to force that ClassLoader to be used by ServiceLoader.

        My preference would be just to use Spring's ServiceListFactoryBean and not have to hack my own subclasses in there, so a fix of this issue (or an explanation of what we're doing wrong) would be very helpful.

        Show
        Ben McDonie added a comment - I am having the EXACT same issue with ServiceListFactoryBean. The following is the hack/workaround that helped me get ServiceLoader using my custom class loader. MyServiceListFactoryBean.java public class MyServiceListFactoryBean extends ServiceListFactoryBean { private ClassLoader realClassLoader; public void setRealClassLoader( ClassLoader realClassLoader) { this .realClassLoader = realClassLoader; } @Override protected Object createInstance() { return getObjectToExpose(ServiceLoader.load(getServiceType(), this .realClassLoader)); } } I basically just inject my custom class loader into this FactoryBean, and then override createInstance() to force that ClassLoader to be used by ServiceLoader. My preference would be just to use Spring's ServiceListFactoryBean and not have to hack my own subclasses in there, so a fix of this issue (or an explanation of what we're doing wrong) would be very helpful.
        Hide
        Juergen Hoeller added a comment -

        Note that setBeanClassLoader is part of the BeanClassLoaderAware contract and therefore a 'special' property that the container fulfills. In order to specify a custom ClassLoader, we'd have to introduce a separate "customClassLoader" property or the like, being picked up instead of the container's one as passed in through setBeanClassLoader.

        Juergen

        Show
        Juergen Hoeller added a comment - Note that setBeanClassLoader is part of the BeanClassLoaderAware contract and therefore a 'special' property that the container fulfills. In order to specify a custom ClassLoader, we'd have to introduce a separate "customClassLoader" property or the like, being picked up instead of the container's one as passed in through setBeanClassLoader. Juergen
        Hide
        Juergen Hoeller added a comment -

        Actually, why are you specifying a custom ClassLoader in the first place - and in particular, why at the ServiceLoaderFactoryBean level? Couldn't you set that custom ClassLoader on your entire ApplicationContext which would make it the ClassLoader that gets propagated through setBeanClassLoaderAware?

        Juergen

        Show
        Juergen Hoeller added a comment - Actually, why are you specifying a custom ClassLoader in the first place - and in particular, why at the ServiceLoaderFactoryBean level? Couldn't you set that custom ClassLoader on your entire ApplicationContext which would make it the ClassLoader that gets propagated through setBeanClassLoaderAware? Juergen
        Hide
        Ben McDonie added a comment -

        Ah ok, thanks for the clarification.
        The intent was just to provide a separate directory where end-users could drop their plugins and have the main application detect them automatically via ServiceLoader. So the custom ClassLoader is really just an extension to allow class loading from jar files in the plugins directory. I suppose this could be the ClassLoader for the entire application – I wasn't sure if that was a recommended approach or not.

        Show
        Ben McDonie added a comment - Ah ok, thanks for the clarification. The intent was just to provide a separate directory where end-users could drop their plugins and have the main application detect them automatically via ServiceLoader. So the custom ClassLoader is really just an extension to allow class loading from jar files in the plugins directory. I suppose this could be the ClassLoader for the entire application – I wasn't sure if that was a recommended approach or not.
        Hide
        Phil Webb added a comment -

        Marking as "Won't Fix" with the assumption that setting the class loader on the ApplicationContext is sufficient.

        Show
        Phil Webb added a comment - Marking as "Won't Fix" with the assumption that setting the class loader on the ApplicationContext is sufficient.
        Hide
        Farrukh Najmi added a comment -

        I am using Spring 3.0.5-RELEASE. I do not see any way to set a custom classloader on ApplicationContext:

        http://javasourcecode.org/html/open-source/spring/spring-3.0.5/org/springframework/context/ApplicationContext.html

        Can someone please tell me what I am missing. Thanks.

        Show
        Farrukh Najmi added a comment - I am using Spring 3.0.5-RELEASE. I do not see any way to set a custom classloader on ApplicationContext: http://javasourcecode.org/html/open-source/spring/spring-3.0.5/org/springframework/context/ApplicationContext.html Can someone please tell me what I am missing. Thanks.
        Hide
        Phil Webb added a comment -

        Farrukh Najmi,

        The ApplicationContext interface does not include a method to set the ClassLoader but most implementations extends DefaultResourceLoader which does:

        http://javasourcecode.org/html/open-source/spring/spring-3.0.5/org/springframework/core/io/DefaultResourceLoader.html#setClassLoader%28java.lang.ClassLoader%29

        Show
        Phil Webb added a comment - Farrukh Najmi , The ApplicationContext interface does not include a method to set the ClassLoader but most implementations extends DefaultResourceLoader which does: http://javasourcecode.org/html/open-source/spring/spring-3.0.5/org/springframework/core/io/DefaultResourceLoader.html#setClassLoader%28java.lang.ClassLoader%29

          People

          • Assignee:
            Phil Webb
            Reporter:
            Farrukh Najmi
            Last updater:
            Phil Webb
          • Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:
              Days since last comment:
              1 year, 5 weeks, 3 days ago