Ask Your Question
1

How to load a classpath resource from a custom Java processor?

asked 2018-08-08 11:07:55 -0600

dcwatson84 gravatar image

updated 2018-08-09 07:24:40 -0600

I'm building a custom processor in Java and I need to load a resource from the classpath. The resource is inside a dependency jar that gets packaged with the processor. The standard way to load classpath resources in java is the method below...

java.lang.Class.getResourceAsStream(String)

However, this does not work from a custom Java processor, it returns null. The resource definitely exists within the deployed dependency .jar file, but the class loader cannot find the resource. It can see the classes in the .jar file, but It can't access the resources.

The dependency jar file contents:

         0 Thu Aug 09 08:02:22 EDT 2018 META-INF/
   133 Thu Aug 09 08:02:20 EDT 2018 META-INF/MANIFEST.MF
     0 Thu Aug 09 08:02:18 EDT 2018 com/
     0 Thu Aug 09 08:02:20 EDT 2018 com/example/
   270 Thu Aug 09 08:02:20 EDT 2018 com/example/MyClass.class
     0 Thu Aug 09 08:02:18 EDT 2018 com/example/sample-resource.txt
     0 Thu Aug 09 08:02:22 EDT 2018 META-INF/maven/
     0 Thu Aug 09 08:02:22 EDT 2018 META-INF/maven/com.example/
     0 Thu Aug 09 08:02:22 EDT 2018 META-INF/maven/com.example/example-resource/
   370 Thu Aug 09 08:02:06 EDT 2018 META-INF/maven/com.example/example-resource/pom.xml
   126 Thu Aug 09 08:02:22 EDT 2018 META-INF/maven/com.example/example-resource/pom.properties

The snippet in the processor where I look for the resource:

@Override
  protected List<ConfigIssue> init() {

    URL url = MyClass.class.getResource("sample-resource.txt");
    LOGGER.info("resource url: {}",url);
    InputStream is = MyClass.class.getResourceAsStream("sample-resource.txt");
    LOGGER.info("resource stream: {}",is);

    List<ConfigIssue> issues = super.init();
    return issues;
  }

Those two log lines output null as the values for those variables.

Note that the resource is not in the processor jar. It's in the dependency jar, which is in the "lib" folder under where the processor jar is installed, as outlined in the docs. No processor parameters even come into play, it's just trying to access the static resource in the init method.

edit retag flag offensive close merge delete

Comments

Can you post the snippet where you actually invoke this including params, as well as the jar tvf output from the jar file?

jeff gravatar imagejeff ( 2018-08-08 22:35:54 -0600 )edit

I added the jar contents and the snippet. I can attach the dependency jar if necessary, but there is nothing special about any of it. It's an empty processor with a mostly empty dependency jar, that attempts to access a resource in the dependency jar, and gets null.

dcwatson84 gravatar imagedcwatson84 ( 2018-08-09 07:23:42 -0600 )edit

1 Answer

Sort by » oldest newest most voted
1

answered 2018-10-09 14:00:21 -0600

jeff gravatar image

Given the jar structure you posted, can you try this instead?

InputStream is = MyClass.class.getResourceAsStream("com/example/sample-resource.txt");

Loading resources through the classpath requires providing the fully qualified path to the resource file within the jar.

edit flag offensive delete link more

Comments

I'll try that, but by default that method does not need the absolute path to load classpath resources - https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getResource(java.lang.String) Paths can be relative to the class package.

dcwatson84 gravatar imagedcwatson84 ( 2018-10-09 14:32:11 -0600 )edit

The Class.getResourceAsStream method simply delegates the call to the classloader. The specific class package name is not used in lookup. http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/lang/Class.java#l2203

jeff gravatar imagejeff ( 2018-10-09 14:37:12 -0600 )edit

Actually it does use the package name, on line 2204 and 2248... name = resolveName(name);

dcwatson84 gravatar imagedcwatson84 ( 2018-10-09 16:23:29 -0600 )edit

Hmm, you're right! In any case, it seems like this is how all of our test classes load their resource files. From a classloader perspective, we aren't doing anything weird (we're basically just extending java.net.URLClassLoader) so I'm not sure why the behavior would be different.

jeff gravatar imagejeff ( 2018-10-09 16:27:31 -0600 )edit

I tried that method and it did not work. Returned resource is still null. Overriding ClassLoader usually causes issues like this, but I don't know exactly which pieces are overridden by the SDC code. Do you have an example of a custom processor that does this?

dcwatson84 gravatar imagedcwatson84 ( 2018-10-10 11:43:37 -0600 )edit
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2018-08-08 11:07:55 -0600

Seen: 74 times

Last updated: Oct 09