Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java getResourceAsStream JAR inside WAR

I have a Java webapp WAR file that depends on multiple jars in it's WEB-INF\lib directory. One of these JARS needs to load some config files by doing class.getClassLoader().getResourceAsStream(...). However the InputStream resturns null. Is there a problem with taking this approach when the JAR is inside a WAR? The app is deployed on Tomcat6.

EDIT MORE INFO:

I'm tring to load in SQL queries from files so I can run them. These are located in a separate DAO jar within the web app's WAR, under WEB-INF/lib

mywebapp.war
        -- WEB-INF
          -- lib
             -- mydao.jar
               ---- com/companyname/queries
                   -- query1.sql
                   -- query2.sql
                   -- query3.sql
                   ...

CODE USING TO LOAD CLASSES

public class QueryLoader {

 private static final Logger LOGGER = Logger.getLogger(QueryLoader.class.getName());

public String loadQuery(String fileName) {
  final String newline = "\n";

  BufferedReader reader = new BufferedReader(new InputStreamReader(         
        QueryLoader.class.getClassLoader().getResourceAsStream(
              "/com/companyname/queries/" + fileName)));
  StringBuilder sb = new StringBuilder();
  String line;
  try {
     while ((line = reader.readLine()) != null) {
        sb.append(line);
        sb.append(newline);
     }
  } catch (IOException e) {
     LOGGER.error(e);
  }

I have also tried changing the getResourceAsStream line to

Thread.currentThread().getContextClassLoader().getResourceAsStream(

without success.

My development environment is MS Windows Vista and but I encounter the same error when running it on this environment and on Ubuntu.

like image 655
Tarski Avatar asked Feb 25 '23 18:02

Tarski


2 Answers

Assuming you're not making the rookie mistake of putting QueryLoader in a different JAR, the only problem I can see is that you're using File.separator yet appear (from your use of \) to be using Windows. When using getResourceAsStream, the separator is always a forward slash (/) just as if you're using a URL.

If I change that I get this:

QueryLoader.class.getClassLoader().getResourceAsStream(
          "/com/companyname/queries/" + fileName)

Of course, if QueryLoader is in the com.companyname.queries package (along with the queries themselves) then you should simply do this:

QueryLoader.class.getResourceAsStream(fileName)

Simple as that. (It's documented that Class.getResourceAsStream qualifies relative filenames with the name of the containing package.)

like image 173
Donal Fellows Avatar answered Mar 07 '23 16:03

Donal Fellows


Managed to get it to work by using Spring's resource loader instead

public String loadQuery(String fileName) {
  final String newline = "\n";

  ApplicationContext ctx = new ClassPathXmlApplicationContext();
  Resource res = ctx.getResource("classpath:/com/msi/queries/" + fileName);
  BufferedReader reader;
  StringBuilder sb = new StringBuilder();
  try {
     reader = new BufferedReader(new InputStreamReader(res.getInputStream()));
     String line;

     while ((line = reader.readLine()) != null) {
        sb.append(line);
        sb.append(newline);
     }
  } catch (IOException e) {
     LOGGER.error(e);
  }

  return sb.toString();

}

like image 30
Tarski Avatar answered Mar 07 '23 16:03

Tarski