Uploaded image for project: 'JBoss Transaction Manager'
  1. JBoss Transaction Manager
  2. JBTM-2189

Bootstrapping from Complex Classloader (OneJar)

    XMLWordPrintable

Details

    • Feature Request
    • Resolution: Can't Do
    • Major
    • None
    • 5.0.1
    • Common
    • None

    Description

      I am using Narayana within a JavaSE application. The application is compiled into a single Jar. When executing, Narayana fails to bootstrap properly.

      The first problem is within com.arjuna.common.util.ConfigurationInfo.

      Lines 111-115 aim to load the MANIFEST file from the classpath:

      String pathToManifest = basePath+"/META-INF/MANIFEST.MF";

      InputStream is = null;
      try {
      is = new URL(pathToManifest).openStream();

      I replaced this with:

      InputStream is = null;

      // BEGIN - WORKAROUND FOR ONE-JAR
      try {
      String targetPrefix = pathToThisClass.substring(0, pathToThisClass.length() - "/com/arjuna/common/util/ConfigurationInfo.class".length());
      Enumeration<URL> resources = ConfigurationInfo.class.getClassLoader().getResources("META-INF/MANIFEST.MF");
      while (resources.hasMoreElements()) {
      URL next = resources.nextElement();
      if (next.toString().startsWith(targetPrefix))

      { is = next.openStream(); break; }

      }
      // END - WORKAROUND FOR ONE-JAR

      This should work for all environments.

      Changes are also required in com.arjuna.common.util.propertyservice.AbstractPropertiesFactory to attempt loading from classpath as well as file system:

      The last line of initDefaultProperties (195) needed changing to:

      defaultProperties = getPropertiesFromClasspath(propertyFileName, PropertiesFactoryStax.class.getClassLoader());
      if (defaultProperties == null)

      { defaultProperties = getPropertiesFromFile(propertyFileName, PropertiesFactoryStax.class.getClassLoader()); }

      }

      and the following methods added / replaced:

      /**

      • Returns the config properties read from a specified relative location on the classpath.
        *
      • @param propertyFileName the file name relative to the classpath root.
      • @return the Properties loaded from the specified source.
        */
        public Properties getPropertiesFromClasspath(String propertyFileName, ClassLoader classLoader) {

      Properties properties = null;

      try {
      Enumeration<URL> resources = ConfigurationInfo.class.getClassLoader().getResources(propertyFileName);
      while (resources.hasMoreElements())

      { URL next = resources.nextElement(); properties = loadFromStream(next.openStream()); return properties; }


      } catch(Exception e)

      { return null; }

      return properties;
      }

      /**

      • Returns the config properties read from a specified location.
        *
      • @param propertyFileName the file name. If relative, this is located using the FileLocator algorithm.
      • @return the Properties loaded from the specified source.
        */
        public Properties getPropertiesFromFile(String propertyFileName, ClassLoader classLoader) {
        String propertiesSourceUri = null;
        try { // This is the point where the search path is applied - user.dir (pwd), user.home, java.home, classpath propertiesSourceUri = com.arjuna.common.util.propertyservice.FileLocator.locateFile(propertyFileName, classLoader); }

        catch(FileNotFoundException fileNotFoundException)

        Unknown macro: { // try falling back to a default file built into the .jar // Note the default- prefix on the name, to avoid finding it from the .jar at the previous stage // in cases where the .jar comes before the etc dir on the classpath. URL url = AbstractPropertiesFactory.class.getResource("/default-"+propertyFileName); if(url == null) { throw new RuntimeException("missing property file "+propertyFileName); } else { propertiesSourceUri = url.toString(); } }

        catch (IOException e)

        { throw new RuntimeException("invalid property file "+propertiesSourceUri, e); }

      Properties properties = null;

      try

      { properties = loadFromFile(propertiesSourceUri); properties = applySystemProperties(properties); }

      catch(Exception e)

      { throw new RuntimeException("unable to load properties from "+propertiesSourceUri, e); }

      return properties;
      }

      private Properties loadFromStream(InputStream inputStream) throws IOException {

      Properties inputProperties = new Properties();
      Properties outputProperties = new Properties();

      try

      { loadFromXML(inputProperties,inputStream); }

      finally

      { inputStream.close(); }

      Enumeration namesEnumeration = inputProperties.propertyNames();
      while(namesEnumeration.hasMoreElements())

      { String propertyName = (String)namesEnumeration.nextElement(); String propertyValue = inputProperties.getProperty(propertyName); propertyValue = propertyValue.trim(); // perform JBossAS style property substitutions. JBTM-369 propertyValue = StringPropertyReplacer.replaceProperties(propertyValue); outputProperties.setProperty(propertyName, propertyValue); }

      return outputProperties;
      }

      Attachments

        Activity

          People

            thjenkin@redhat.com Tom Jenkinson
            chrisph Chris Pheby (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: