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
Spring resource classpath issue Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring resource classpath issue

    Hi,

    I'm trying to deploy a spring based bundle in osgi (fuse esb).In
    spring context, I'm referring to a db4o file which is inside resources
    folder. As per my understanding, a maven project will make sure that
    any file available under resources folder will be available in project
    classpath. I've kept the file under
    src/main/resources/repo/test.db4o.

    Here's the entry in spring context.

    <bean id="objectContainer"
    class="org.springmodules.db4o.ObjectContainerFacto ryBean">
    <property name="databaseFile"
    value="classpath:/repo/test.db4o" />
    </bean>

    Once I install and try to start the application, I'm getting the
    following exception.

    "java.io.FileNotFoundException: OSGi
    resource[classpath:/repo/test.db4o|bnd.id=258|bnd.sym=taxonomydaoimplbundle]
    cannot be resolved to absolute file path because it does not reside in
    the file system: bundle://258.0:1/repo/test.db4o"

    I've tried different combinations, but Felix doesn't seem to recognize
    this file. Any pointer will be appreciated.

    - Thanks

  • #2
    Try to write:
    <property name="databaseFile" value="classpath:repo/test.db4o" />

    Comment


    • #3
      Originally posted by polosatiy View Post
      Try to write:
      <property name="databaseFile" value="classpath:repo/test.db4o" />
      I tried out all possible combinations, but doesn't seem to work. I even tried <property name="databaseFile" value="classpath*:repo/test.db4o" /> w/o any luck.

      Comment


      • #4
        Originally posted by back2grave View Post
        I tried out all possible combinations, but doesn't seem to work. I even tried <property name="databaseFile" value="classpath*:repo/test.db4o" /> w/o any luck.
        Show manifest of your bundle.

        Comment


        • #5
          Originally posted by polosatiy View Post
          Show manifest of your bundle.
          Here's the manifest file entry :

          Manifest-Version: 1.0
          Export-Package: com.test.taxonomy.dao.api;uses:="com.test.taxo
          nomy.message,com.test.taxonomy.model";version="1.0 .0"
          Bundle-ClassPath: .,slf4j-api-1.6.1.jar,spring-modules-db4o-0.9.jar,co
          mmons-lang-2.5.jar,slf4j-simple-1.6.1.jar,commons-logging-1.1.1.jar,c
          ommons-collections-3.2.1.jar,db4o-7.12.jar
          Built-By: bandops
          Tool: Bnd-0.0.357
          Bundle-Name: Taxonomy Dao Impl Bundle
          Created-By: Apache Maven Bundle Plugin
          Build-Jdk: 1.6.0_21
          Bundle-Version: 1.0.0
          Bnd-LastModified: 1308173187970
          Embed-Transitive: true
          Bundle-Activator: com.test.taxonomy.dao.impl.activator.TaxonomyDao
          ImplActivator
          Bundle-ManifestVersion: 2
          Embed-Dependency: *;scope=compile|runtime;artifactId=!spring|co
          mmons-logging|org.apache.felix.framework|taxonomymessage bundle|taxono
          mymodelbundle
          Import-Package: com.test.taxonomy.dao.api;resolution:=optional;ver
          sion="1.0",com.test.taxonomy.message;version="1.0. 0",com.test
          .taxonomy.model;version="1.0.0",javax.management;r esolution:=optional
          ,javax.net;resolution:=optional,javax.net.ssl;reso lution:=optional,ja
          vax.servlet;resolution:=optional,org.apache.avalon .framework.logger;r
          esolution:=optional,org.apache.log;resolution:=opt ional,org.apache.lo
          g4j;resolution:=optional,org.apache.tools.ant;reso lution:=optional,or
          g.apache.tools.ant.types;resolution:=optional,org. apache.tools.ant.ty
          pes.resources;resolution:=optional,org.apache.tool s.ant.util.regexp;r
          esolution:=optional,org.osgi.framework;resolution: =optional;version="
          1.5",org.springframework.beans.factory;resolution: =optional;version="
          2.5",org.springframework.context.support;resolutio n:=optional;version
          ="2.5",org.springframework.core;resolution:=option al;version="2.5",or
          g.springframework.core.io;resolution:=optional;ver sion="2.5",org.spri
          ngframework.dao;resolution:=optional;version="2.5" ,org.springframewor
          k.dao.support;resolution:=optional;version="2.5",o rg.springframework.
          transaction;resolution:=optional;version="2.5",org .springframework.tr
          ansaction.annotation;resolution:=optional;version= "2.5",org.springfra
          mework.transaction.support;resolution:=optional;ve rsion="2.5",org.spr
          ingframework.util;resolution:=optional;version="2. 5"
          Bundle-SymbolicName: taxonomydaoimplbundle

          Comment


          • #6
            Does your bundle contains "repo/test.db4o" in jar file?

            That's very strange behavior. Here is my example:

            Code:
            <bean id="settingsBean" class="ru.test.MyBean">
                    <property name="settings" value="classpath:ru/test/beansettings.xml"/>
            </bean>
            Code:
            class MyBean {
                private Resource settings;
            }
            and it's works.

            Comment


            • #7
              Originally posted by polosatiy View Post
              Does your bundle contains "repo/test.db4o" in jar file?

              That's very strange behavior. Here is my example:

              Code:
              <bean id="settingsBean" class="ru.test.MyBean">
                      <property name="settings" value="classpath:ru/test/beansettings.xml"/>
              </bean>
              Code:
              class MyBean {
                  private Resource settings;
              }
              and it's works.
              The bundle does contains the test.db4o file. I looked into the stacktrace and here's what I see.

              Code:
              "caused by: java.io.FileNotFoundException: OSGi
              resource[classpath:taxonomy.db4o|
              nd.id=335|bnd.sym=taxonomydaoimplbundle] cannot be resolved to
              absolute file path
                     at org.springframework.osgi.io.OsgiBundleResource.getFile(OsgiBundleResorce.java:345)
                     at org.springmodules.db4o.ObjectContainerFactoryBean.afterPropertiesSet(bjectContainerFactoryBean.java:104)
                     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
                     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
                     ... 45 more
              aused by: java.io.FileNotFoundException: OSGi
              resource[classpath:taxonomy.db4o|nd.id=335|bnd.sym=taxonomydaoimplbundle]
              cannot be resolved to absolute file pah because it does not reside in
              the file system: bundle://335.0:1/taxonomy.db4o
              
                     at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:242
              
                     at org.springframework.osgi.io.OsgiBundleResource.getFile(OsgiBundleReso
              rce.java:342)
                     ... 48 more"
              The exception is being thrown from spring OsgiBundleResource.getFile() method.

              It happens when spring module ObjectContainerFactoryBean is trying to
              execute the following code :

              Code:
              if (databaseFile != null) {
                      container = Db4o.openFile(configuration,
              databaseFile.getFile().getAbsolutePath());
                     log.info("opened db4o local file-based objectContainer @" +
              ObjectUtils.getIdentityHexString(container));
              }
              databaseFile is a org.springframework.core.io.Resource object whose
              value is being injected by spring app context, i.e. the db4o path
              (classpath:META-INF/spring/repo/test.db4o) . The exception is
              happening at OsgiBundleResource.getFile() when
              ObjectContainerFactoryBean is trying to execute
              databaseFile.getFile().getAbsolutePath()).

              Here's the getFile() method in OsgiBundleResource.
              Code:
              public File getFile() throws IOException {
                              // locate the file inside the bundle only known prefixes
                              if (searchType != OsgiResourceUtils.PREFIX_TYPE_UNKNOWN) {
                                      String bundleLocation = bundle.getLocation();
                                      int prefixIndex = bundleLocation.indexOf(ResourceUtils.FILE_URL_PREFIX);
                                      if (prefixIndex > -1) {
                                              bundleLocation = bundleLocation.substring(prefixIndex +
              ResourceUtils.FILE_URL_PREFIX.length());
                                      }
                                      File file = new File(bundleLocation, path);
                                      if (file.exists()) {
                                              return file;
                                      }
                                      // fall back to the URL discovery (just in case)
                              }
              
                              try {
                                      return ResourceUtils.getFile(getURI(), getDescription());
                              }
                              catch (IOException ioe) {
                                      throw (IOException) new FileNotFoundException(getDescription()
                                                      + " cannot be resolved to absolute file path").initCause(ioe);
              Similar to your example, the ObjectContainerFactoryBean is being injected with test.db4o file as a Resource object. I'm guessing, OsgiBundleResource is the one who's doing to discovery and subsequent load of the file. I've no idea why it doesn't work for me.

              Comment


              • #8
                Just curious, once you get the Resource object, how are you loading the file? Are you using InputStream or File object.

                Comment


                • #9
                  Originally posted by back2grave View Post
                  Just curious, once you get the Resource object, how are you loading the file? Are you using InputStream or File object.
                  I use URL.

                  Code:
                  URL url = settings.getURL();
                  url.openStream();
                  Can you post debug information about databaseFile? What is it value? It seems that OsgiResourceUtils#getSearchType method doesn't recognize correct prefix.

                  Comment


                  • #10
                    Originally posted by polosatiy View Post
                    I use URL.

                    Code:
                    URL url = settings.getURL();
                    url.openStream();
                    Can you post debug information about databaseFile? What is it value? It seems that OsgiResourceUtils#getSearchType method doesn't recognize correct prefix.
                    Not sure I understand clearly the debug information about the databaseFile ? Can you please rephrase ? My idea about getSearchType value should be "classpath" as specified in the spring config.

                    Comment


                    • #11
                      I've just checked "getFile()" method and I've found an error.

                      The problem with this line:

                      Code:
                      ResourceUtils.getFile(getURI(), getDescription());
                      URI starts from "bundle", but ResourceUtils expects "file". That's why is doesn't work.

                      Try to use URL or InputStream.

                      Comment


                      • #12
                        Originally posted by polosatiy View Post
                        I've just checked "getFile()" method and I've found an error.

                        The problem with this line:

                        Code:
                        ResourceUtils.getFile(getURI(), getDescription());
                        URI starts from "bundle", but ResourceUtils expects "file". That's why is doesn't work.

                        Try to use URL or InputStream.
                        So what you are saying is a bug with the spring ResourceUtils ? I guessthe value of URI getting passed is "bundle://258.0:1/repo/test.db4o".

                        In ResourceUtils.getFile(),

                        Code:
                        if (!URL_PROTOCOL_FILE.equals(resourceUrl.getProtocol())) {
                        			throw new FileNotFoundException(
                        					description + " cannot be resolved to absolute file path " +
                        					"because it does not reside in the file system: " + resourceUrl);
                        		}
                        Here its expecting "file" but getting "bundle" and hence the exception. Thanks for debugging this for me.

                        But the follow-up question is how its so obvious that the protocol will be a file ? Any resource uri deployed in an OSGi bundle will always start with a bundle. Isn't this a bug ? My problem now is, the ObjectContainerFactoryBean is a third party code which I've little control over. Moreover, the inherent call to Db4o.openFile() is the only method available, so getting File is the only choice. Not sure how to resolve this now.

                        Comment


                        • #13
                          I think It's a bug and I've posted a bug to tracker
                          https://jira.springsource.org/browse/OSGI-818

                          If you need to use a file, I can suggest you to copy InputSteam from URL to a temp file like this:

                          Code:
                          InputStream is = resource.getURL().openStream();
                          File file  = File.createTempFile("tmp", "prop");
                          FileOutputStream os = new FileOutputStream(file);
                          //code to copy from is to os;

                          Comment


                          • #14
                            Thanks for all your help in getting this issue resolved. I followed your clue and tried couple of approaches which worked.

                            1. Externalizing the file and use file:///absolute_file_path

                            2. I extended ObjectContainerFactoryBean and instead and overriden the method to use inputstream and generate the file instead of using the getFile() from OSGiBundleResource.

                            But now, I've got into another issue which is has lead me to open another thread :-).

                            Appreciate your help....

                            Comment

                            Working...
                            X