Announcement Announcement Module
Collapse

Spring Dynamic Modules forum decommissioned in favor of Eclipse Gemini Blueprint

With the official first release of Eclipse Gemini Blueprint shipped, the migration of the Spring Dynamic Modules code base to the Eclipse Foundation, as part of the Gemini project, has been completed.

As such, this forum has been decommissioned in favour of the Eclipse Gemini forums.
See more
See less
Best Practice for OSGi Bundle Repository? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Best Practice for OSGi Bundle Repository?

    Hello,

    I'm developing an application based on Eclipse-RCP with Spring and Hibernate. When I noticed that SpringSource has published a OSGi Bundle Repository for Enterprise Libraries i tried to setup a new Eclipse-Target Platform with the base Eplipse-Bundles (org.eclipse.core.*, org.eclipse.equinox.*, org.eclipse.jface.*, ...) and to add Spring and Hibernate to my new Target Platform by checking out all org.springframework.* - Bundles and all com.springsource.org.hibernate.* from the SpringSource OSGi Bundle Repository.
    Everything works fine so far. I can reference the Spring- and Hibernateclasses from within my Bundles by making my Bundle dependend on the Spring- an Hibernatebundles from my Target Platform (no compilererrors).

    The problems started when my application started

    The first problem was, that i got a java.io.FileNotFoundException from the class org.springframework.core.io.ClassPathResource, which couldn't find my appcontext.xml-File. Ok, this is clear. My appcontext.xml is not visible for the classloader which loads the class org.springframework.core.io.ClassPathResource, because org.springframework.core.io.ClassPathResource is in the OSGI-Bundle org.springframework.core and this bundle has its own classloader. My bundle with appcontext.xml has a different classloader.

    Because im using Equinox i thought i can solve the problem by declaring org.springframework.core and org.springframework.beans as buddys of my bundle by adding 'Eclipse-RegisterBuddy: org.springframework.beans, org.springframework.core' to my MANIFEST.MF. This didn't work because to use the Equinox Buddy-Mechanism the Buddy has to declare a Eclipse-BuddyPolicy.
    So i modified the bundles org.springframework.core and org.springframework.beans and added 'Eclipse-BuddyPolicy: registered' to their MANIFEST.MF. This worked and the java.io.FileNotFoundException wasn't thrown again.

    The next Problem i have is, that in my appcontext.xml i declare a bean as follows:

    <bean id="datasource"
    class="org.springframework.jdbc.datasource.DriverM anagerDataSource">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
    <property name="url" value="jdbc:oracle:thin:at myServer:1521:myDb"/>
    <property name="username" value="user"/>
    <property name="password" value="pw"/>
    </bean>

    So when i try to start my App. i get this:

    PropertyAccessException 1: org.springframework.beans.MethodInvocationExceptio n: Property 'driverClassName' threw exception; nested exception is java.lang.IllegalStateException: Could not load JDBC driver class [oracle.jdbc.driver.OracleDriver]
    org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'sessionFactory' defined in class path resource [appContext.xml]: Cannot resolve reference to bean 'datasource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'datasource' defined in class path resource [appContext.xml]: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateExcep tion; nested PropertyAccessExceptions (1) are:
    PropertyAccessException 1: org.springframework.beans.MethodInvocationExceptio n: Property 'driverClassName' threw exception; nested exception is java.lang.IllegalStateException: Could not load JDBC driver class [oracle.jdbc.driver.OracleDriver]
    at org.springframework.beans.factory.support.BeanDefi nitionValueResolver.resolveReference(BeanDefinitio nValueResolver.java:275)
    at org.springframework.beans.factory.support.BeanDefi nitionValueResolver.resolveValueIfNecessary(BeanDe finitionValueResolver.java:104)
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.applyPropertyValues(Abs tractAutowireCapableBeanFactory.java:1245)
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.populateBean(AbstractAu towireCapableBeanFactory.java:1010)
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.doCreateBean(AbstractAu towireCapableBeanFactory.java:472)
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory$1.run(AbstractAutowireC apableBeanFactory.java:409)
    at java.security.AccessController.doPrivileged(Native Method)
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.createBean(AbstractAuto wireCapableBeanFactory.java:380)
    at org.springframework.beans.factory.support.Abstract BeanFactory$1.getObject(AbstractBeanFactory.java:2 64)
    at org.springframework.beans.factory.support.DefaultS ingletonBeanRegistry.getSingleton(DefaultSingleton BeanRegistry.java:222)
    at org.springframework.beans.factory.support.Abstract BeanFactory.doGetBean(AbstractBeanFactory.java:261 )
    at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:185)
    at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:164)
    at org.springframework.beans.factory.support.DefaultL istableBeanFactory.preInstantiateSingletons(Defaul tListableBeanFactory.java:423)
    at org.springframework.context.support.AbstractApplic ationContext.finishBeanFactoryInitialization(Abstr actApplicationContext.java:728)
    at org.springframework.context.support.AbstractApplic ationContext.refresh(AbstractApplicationContext.ja va:380)
    at testgenerator.spring.SpringStarter.createContext(S pringStarter.java:75)
    at testgenerator.spring.SpringStarter.getApplicationC ontext(SpringStarter.java:31)
    at testgenerator.spring.SpringStarter.main(SpringStar ter.java:82)
    at testgenerator.Activator.start(Activator.java:32)
    at org.eclipse.osgi.framework.internal.core.BundleCon textImpl$2.run(BundleContextImpl.java:1009)
    at java.security.AccessController.doPrivileged(Native Method)
    at org.eclipse.osgi.framework.internal.core.BundleCon textImpl.startActivator(BundleContextImpl.java:100 3)
    at org.eclipse.osgi.framework.internal.core.BundleCon textImpl.start(BundleContextImpl.java:984)
    at org.eclipse.osgi.framework.internal.core.BundleHos t.startWorker(BundleHost.java:346)
    at org.eclipse.osgi.framework.internal.core.AbstractB undle.resume(AbstractBundle.java:355)
    at org.eclipse.osgi.framework.internal.core.Framework .resumeBundle(Framework.java:1074)
    at org.eclipse.osgi.framework.internal.core.StartLeve lManager.resumeBundles(StartLevelManager.java:616)
    at org.eclipse.osgi.framework.internal.core.StartLeve lManager.incFWSL(StartLevelManager.java:508)
    at org.eclipse.osgi.framework.internal.core.StartLeve lManager.doSetStartLevel(StartLevelManager.java:29 9)
    at org.eclipse.osgi.framework.internal.core.StartLeve lManager.dispatchEvent(StartLevelManager.java:489)
    at org.eclipse.osgi.framework.eventmgr.EventManager.d ispatchEvent(EventManager.java:211)
    at org.eclipse.osgi.framework.eventmgr.EventManager$E ventThread.run(EventManager.java:321)
    Caused by: org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'datasource' defined in class path resource [appContext.xml]: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateExcep tion; nested PropertyAccessExceptions (1) are:
    PropertyAccessException 1: org.springframework.beans.MethodInvocationExceptio n: Property 'driverClassName' threw exception; nested exception is java.lang.IllegalStateException: Could not load JDBC driver class [oracle.jdbc.driver.OracleDriver]
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.applyPropertyValues(Abs tractAutowireCapableBeanFactory.java:1279)
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.populateBean(AbstractAu towireCapableBeanFactory.java:1010)
    ... 32 more
    Caused by: org.springframework.beans.PropertyBatchUpdateExcep tion; nested PropertyAccessExceptions (1) are:
    PropertyAccessException 1: org.springframework.beans.MethodInvocationExceptio n: Property 'driverClassName' threw exception; nested exception is java.lang.IllegalStateException: Could not load JDBC driver class [oracle.jdbc.driver.OracleDriver]
    at org.springframework.beans.AbstractPropertyAccessor .setPropertyValues(AbstractPropertyAccessor.java:1 04)
    at org.springframework.beans.AbstractPropertyAccessor .setPropertyValues(AbstractPropertyAccessor.java:5 9)
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.applyPropertyValues(Abs tractAutowireCapableBeanFactory.java:1276)
    ... 43 more

    I know that the problem is the same as with my appcontext.xml-File. A class in a Bundle can't see the class oracle.jdbc.driver.OracleDriver, which is visible in my bundle. Which bundle is trying to instantiate the class oracle.jdbc.driver.OracleDriver and is not on the Buddy-List of my Bundle?

    Now I'm in doubt if my approach is right. Is it possible, that i have to modify the bundles from the OSGi Bundle Repository so that they can read a appContext.xml from my bundle? Knowing that Eclipse-RegisterBuddy is Equinox-specific, how can this problem be solved whith standard OSGI-machanisms.

    Can anyone please tell my, if there is a best practice to solve my problem?

    Thank you in advance,
    Rudi

  • #2
    Rudi, while you can modify the bundles for the bundle repository I would strongly advice against that. Your visibility issue can be solved if you are able to determine the relationship between the classloaders and the classes that are not seen.
    My advice is to give dm Server a try and test your application - it provides the best OSGI experience for newbies and experts a like as it addresses most of the rough edges that sometimes can be blocking.
    Even if that's not an issue, I recommend you start with a simple example from Spring DM or DM server and then try to build on that. The module visibility and class imports can be tricky at first.

    Comment


    • #3
      Hi rudi s,
      Costin was right that you would better start with DM's simple sample to really understand DM's architecture.

      When I review your problems, I think your app might be on a wrong direction.

      Yours

      Comment


      • #4
        Hi Costin, hi gengshg,

        I will give a look at DM.

        thank you for your replies,
        Rudi

        Comment


        • #5
          Hi Costin,

          to my experience this is a common problem with all abstract-factory-related stuff in bundle environments.
          You can, before tearing up the application context, either call setClassloader on your applicaton context (see static.springframework.org/spring/docs/2.0.x/api/org/springframework/core/io/DefaultResourceLoader.html#setClassLoader(java.lan g.ClassLoader) ) or set the thread's context classloader to the classloader of your own bundle, that is, where your appcontext.xml is placed and your jdbc driver bundle is referenced.
          This would like like this:

          <pre>
          Classloader tmp = Thread.currentThread().getContextClassloader();
          Thread.currentThread().setContextClassloader(MySer viceLocator.class.getClassloader())
          BeanFactory context = new ClassPathXmlApplicationContext(String configLocation);
          Thread.currentThread().setContextClassloader(tmp);
          </pre>

          Hope this helps,

          Armin

          Comment


          • #6
            Armin, thanks for the information though I'm not sure why you're giving it to me .
            The application context does have the proper classloader setup and in fact, all of its classes are loaded through it.
            For services, whether exported or imported, Spring DM can manage the TCCL if you want it to so there is no need to set that up manually (not to mention that the setup can be easily disrupted if some other entity overrides the TCCL).

            Cheers,

            Comment

            Working...
            X