rome
  1. rome
  2. ROME-158

Rome fails to initialize when bundled with an application deployed to Felix/OSGi

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: current
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None

      Description

      The Rome library fails to initialize when bundled with an application deployed to Felix. The failure to initialize manifests itself through Rome's com.sun.syndication.io.impl.PropertiesLoader constructor throwing a NullPointerException when asked to load the "com/sun/syndication/rome.properties" resource, which is also embedded in the (same) Rome JAR file:

      Caused by: java.lang.NullPointerException
      at java.util.Properties$LineReader.readLine(Properties.java:434)
      at java.util.Properties.load0(Properties.java:353)
      at java.util.Properties.load(Properties.java:341)
      at
      com.sun.syndication.io.impl.PropertiesLoader.<init>(PropertiesLoader.java:74)
      at
      com.sun.syndication.io.impl.PropertiesLoader.getPropertiesLoader(PropertiesLoader.java:46)
      at com.sun.syndication.io.impl.PluginManager.<init>(PluginManager.java:54)
      at com.sun.syndication.io.impl.PluginManager.<init>(PluginManager.java:46)
      at com.sun.syndication.feed.synd.impl.Converters.<init>(Converters.java:40)
      at
      com.sun.syndication.feed.synd.SyndFeedImpl.<clinit>(SyndFeedImpl.java:61)
      ... 23 more

      See below for full stack trace.

      The current com.sun.syndication.io.impl.PropertiesLoader constructor code attempts to load the requested "com/sun/syndication/rome.properties" resource from the classloader returned by a call to Thread.currentThread().getContextClassLoader().

      This just happens to work if the (web) application that integrates ROME is deployed on Tomcat, where the Tomcat container sets the Thread's ContextClassLoader to be the same as the classloader that loaded the (web) application (instance of org.apache.catalina.loader.WebappClassLoader), before dispatching any requests to it on that Thread.

      However, this does not work if the application that bundles ROME is deployed to Felix (and most likely other OSGi implementations), where the Thread's context classloader is not explicitly set. In the case of Felix, the classloader returned by Thread.currentThread().getContextClassLoader() is an instance of sun.misc.Launcher$AppClassLoader, which does not have any visibility into any application specific JAR-files (ROME in this case), causing the call to

      java.lang.ClassLoader#getResourceAsStream("com/sun/syndication/rome.properties")

      to return NULL, which results in the NullPointerException mentioned above, when NULL is passed to java.util.Properties#load.

      The proposed fix (see diffs below) replaces the java.lang.Thread#getContextClassLoader() call with com.sun.syndication.io.impl.PropertiesLoader.class.getClassLoader(), which returns the classloader that loaded the
      com/sun/syndication/io/impl/PropertiesLoader.class resource (Java class file). This classloader is able to load any resources embedded in the same JAR file as com/sun/syndication/io/impl/PropertiesLoader.class, including "com/sun/syndication/rome.properties".

      The proposed fix works with Tomcat, Felix, or any other platform.

      The remaining proposed changes in the diffs are of the same nature (replacing Thread.currentThread().getContextClassLoader() with Class#getClassLoader()), and are required because the Rome code caches artifacts such as PropertiesLoader and FeedGenerators in a Map, using the classloader that loaded them as the lookup key.

      ---------------------------------------------------------
      Full stack trace:

      [2013/07/09:20:57:18] (BaseExecute.java:224) INFO
      com.yahoo.yql.api.execute.BaseExecute: Execute error
      java.lang.ExceptionInInitializerError
      at com.sun.syndication.io.SyndFeedInput.build(SyndFeedInput.java:149)
      at
      com.yahoo.yql.execute.java.tables.impl.FeedNormalizerTable.normalize(FeedNormalizerTable.java:99)
      at
      com.yahoo.yql.execute.java.tables.impl.FeedNormalizerTable.normalizeXmlWithXslLiteralFunction(FeedNormalizerTable.java:601)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at
      sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at
      sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:601)
      at
      com.yahoo.yql.resources.JavaExecuteMethod.invoke(JavaExecuteMethod.java:36)
      at
      com.yahoo.yql.execute.java.JavaExecuteMethodInvocation.invoke(JavaExecuteMethodInvocation.java:139)
      at com.yahoo.yql.execute.java.JavaExecute.execute(JavaExecute.java:74)
      at com.yahoo.yql.api.execute.BaseExecute.execute(BaseExecute.java:140)
      at
      com.yahoo.yql.table.module.operator.ExecuteFilter.nextItem(ExecuteFilter.java:68)
      at com.yahoo.yql.api.model.SourceImpl.next(SourceImpl.java:109)
      at com.yahoo.yql.compiler.module.Output.nextItem(Output.java:33)
      at com.yahoo.yql.api.model.SourceImpl.next(SourceImpl.java:109)
      at com.yahoo.yql.core.query.QueryEngine.executePipe(QueryEngine.java:150)
      at
      com.yahoo.yql.execute.js.JavascriptQuery$2.call(JavascriptQuery.java:279)
      at
      com.yahoo.yql.execute.js.JavascriptQuery$2.call(JavascriptQuery.java:219)
      at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
      at java.util.concurrent.FutureTask.run(FutureTask.java:166)
      at
      java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
      at
      java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
      at java.lang.Thread.run(Thread.java:722)
      Caused by: java.lang.NullPointerException
      at java.util.Properties$LineReader.readLine(Properties.java:434)
      at java.util.Properties.load0(Properties.java:353)
      at java.util.Properties.load(Properties.java:341)
      at
      com.sun.syndication.io.impl.PropertiesLoader.<init>(PropertiesLoader.java:74)
      at
      com.sun.syndication.io.impl.PropertiesLoader.getPropertiesLoader(PropertiesLoader.java:46)
      at com.sun.syndication.io.impl.PluginManager.<init>(PluginManager.java:54)
      at com.sun.syndication.io.impl.PluginManager.<init>(PluginManager.java:46)
      at com.sun.syndication.feed.synd.impl.Converters.<init>(Converters.java:40)
      at
      com.sun.syndication.feed.synd.SyndFeedImpl.<clinit>(SyndFeedImpl.java:61)
      ... 23 more

      ---------------------------------------------------------
      Proposed fix (diffs):

      diff -ur com/sun/syndication/io/WireFeedInput.java /Users/jluehe/Desktop/ws/v2/thirdparty/rome/trunk/src/main/java/com/sun/syndication/io/WireFeedInput.java
      — com/sun/syndication/io/WireFeedInput.java 2008-12-08 14:49:46.000000000 -0800
      +++ /Users/jluehe/Desktop/ws/v2/thirdparty/rome/trunk/src/main/java/com/sun/syndication/io/WireFeedInput.java 2013-07-09 15:37:40.000000000 -0700
      @@ -59,10 +59,10 @@
      private static FeedParsers getFeedParsers() {
      synchronized(WireFeedInput.class) {
      FeedParsers parsers = (FeedParsers)

      • clMap.get(Thread.currentThread().getContextClassLoader());
        + clMap.get(WireFeedInput.class.getClassLoader());
        if (parsers == null) { parsers = new FeedParsers(); - clMap.put(Thread.currentThread().getContextClassLoader(), parsers); + clMap.put(WireFeedInput.class.getClassLoader(), parsers); }

        return parsers;
        }
        diff -ur com/sun/syndication/io/WireFeedOutput.java /Users/jluehe/Desktop/ws/v2/thirdparty/rome/trunk/src/main/java/com/sun/syndication/io/WireFeedOutput.java

          • com/sun/syndication/io/WireFeedOutput.java 2009-01-08 08:46:12.000000000 -0800
            +++ /Users/jluehe/Desktop/ws/v2/thirdparty/rome/trunk/src/main/java/com/sun/syndication/io/WireFeedOutput.java 2013-07-09 15:49:06.000000000 -0700
            @@ -48,10 +48,10 @@
            private static FeedGenerators getFeedGenerators() {
            synchronized(WireFeedOutput.class) {
            FeedGenerators generators = (FeedGenerators)
      • clMap.get(Thread.currentThread().getContextClassLoader());
        + clMap.get(WireFeedOutput.class.getClassLoader());
        if (generators == null) { generators = new FeedGenerators(); - clMap.put(Thread.currentThread().getContextClassLoader(), generators); + clMap.put(WireFeedOutput.class.getClassLoader(), generators); }

        return generators;
        }
        diff -ur com/sun/syndication/io/impl/PluginManager.java /Users/jluehe/Desktop/ws/v2/thirdparty/rome/trunk/src/main/java/com/sun/syndication/io/impl/PluginManager.java

          • com/sun/syndication/io/impl/PluginManager.java 2009-01-09 15:53:34.000000000 -0800
            +++ /Users/jluehe/Desktop/ws/v2/thirdparty/rome/trunk/src/main/java/com/sun/syndication/io/impl/PluginManager.java 2013-07-23 10:49:59.000000000 -0700
            @@ -129,7 +129,7 @@
            *
            */
            private Class[] getClasses() throws ClassNotFoundException {
      • ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        + ClassLoader classLoader = PluginManager.class.getClassLoader();
        List classes = new ArrayList();
        boolean useLoadClass = Boolean.valueOf(System.getProperty("rome.pluginmanager.useloadclass", "false")).booleanValue();
        for (int i = 0; i <_propertyValues.length; i++) {
        diff -ur com/sun/syndication/io/impl/PropertiesLoader.java /Users/jluehe/Desktop/ws/v2/thirdparty/rome/trunk/src/main/java/com/sun/syndication/io/impl/PropertiesLoader.java
          • com/sun/syndication/io/impl/PropertiesLoader.java 2007-08-01 02:28:08.000000000 -0700
            +++ /Users/jluehe/Desktop/ws/v2/thirdparty/rome/trunk/src/main/java/com/sun/syndication/io/impl/PropertiesLoader.java 2013-07-23 10:49:59.000000000 -0700
            @@ -40,11 +40,11 @@
            public static PropertiesLoader getPropertiesLoader() {
            synchronized(PropertiesLoader.class) {
            PropertiesLoader loader = (PropertiesLoader)
      • clMap.get(Thread.currentThread().getContextClassLoader());
        + clMap.get(PropertiesLoader.class.getClassLoader());
        if (loader == null) {
        try { loader = new PropertiesLoader(MASTER_PLUGIN_FILE, EXTRA_PLUGIN_FILE); - clMap.put(Thread.currentThread().getContextClassLoader(), loader); + clMap.put(PropertiesLoader.class.getClassLoader(), loader); }

        catch (IOException ex) {
        throw new RuntimeException(ex);
        @@ -66,7 +66,7 @@
        */
        private PropertiesLoader(String masterFileLocation,String extraFileLocation) throws IOException {
        List propertiesList = new ArrayList();

      • ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        + ClassLoader classLoader = PropertiesLoader.class.getClassLoader();

      try {
      InputStream is = classLoader.getResourceAsStream(masterFileLocation);

        Activity

        There are no comments yet on this issue.

          People

          • Assignee:
            Unassigned
            Reporter:
            jluehe
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated: