10

Hiii... I want to get the content of properties file into InputStream class object using getSystemResourceAsStream(). I have built the sample code. It works well using main() method,but when i deploy the project and run on the server, properties file path cannot obtained ... so inputstream object store null value.

Sample code is here..

public class ReadPropertyFromFile {

    public static Logger logger = Logger.getLogger(ReadPropertyFromFile.class);

    public static String readProperty(String fileName, String propertyName) {
        String value = null;
        try {
            //fileName = "api.properties";
            //propertyName = "api_loginid";

            System.out.println("11111111...In the read proprty file.....");


            //  ClassLoader loader = ClassLoader.getSystemClassLoader();

            InputStream inStream = ClassLoader.getSystemResourceAsStream(fileName);

            System.out.println("In the read proprty file.....");
            System.out.println("File Name :" + fileName);
            System.out.println("instream = "+inStream);

            Properties prop = new Properties();

            try {
                prop.load(inStream);
                value = prop.getProperty(propertyName);
            } catch (Exception e) {
                logger.warn("Error occured while reading property " + propertyName + " = ", e);
                return null;
            }
        } catch (Exception e) {
            System.out.println("Exception = " + e);
        }
        return value;
    }

    public static void main(String args[]) {

      System.out.println("prop value = " + ReadPropertyFromFile.readProperty("api.properties", "api_loginid"));
   }
}
skaffman
  • 398,947
  • 96
  • 818
  • 769
Hitesh Solanki
  • 403
  • 2
  • 5
  • 9
  • 3
    Why are using using the system classloader, rather than the normal one? – skaffman Mar 26 '10 at 09:46
  • Note: As of Java9+ the system classloader p.k.a the application classloader _is_ the 'normal' one i.e the grandchild of the bootstrap classloader and child of the platform classloader, see the accepted answer at https://stackoverflow.com/questions/46494112/classloaders-hierarchy-in-java-9 – 8bitjunkie Feb 18 '20 at 14:01

3 Answers3

17

i deploy the project and run on the server,

This sounds like a JSP/Servlet webapplication. In that case, you need to use the ClassLoader which is obtained as follows:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

This one has access to the all classpath paths tied to the webapplication in question and you're not anymore dependent on which parent classloader (a webapp has more than one!) has loaded your class.

Then, on this classloader, you need to just call getResourceAsStream() to get a classpath resource as stream, not the getSystemResourceAsStream() which is dependent on how the webapplication is started. You don't want to be dependent on that as well since you have no control over it at external hosting:

InputStream input = classLoader.getResourceAsStream("filename.extension");

This is finally more robust than your initial getSystemResourceAsStream() approach and the Class#getResourceAsStream() as suggested by others.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
7

The SystemClassLoader loads resources from java.class.path witch maps to the system variable CLASSPATH. In your local application, you probably have the resource your trying to load configured in java.class.path variable. In the server, it's another story because most probably the server loads your resources from another class loader.

Try using the ClassLoader that loaded class using the correct path:

getClass().getResourceAsStream(fileName);

This article might also be useful.

bruno conde
  • 47,767
  • 15
  • 98
  • 117
0

Try using getResourceAsStream() instead of getSystemResourceAsStream().

8bitjunkie
  • 12,793
  • 9
  • 57
  • 70
Chandra Sekar
  • 10,683
  • 3
  • 39
  • 54
  • 1) Beware of calling `Class.getResourceAsStream(name)` directly on the `Class` class - it prepends `name` with the package path to the class instance you called it on. 2) Calling `this.getClass().getClassLoader().getResourceAsStream(name)` and `ClassLoader.getSystemResourceAsStream(name)` are almost always equivalent. They start with the system classloader, both call through `ClassLoader.getResource(name)` where it recursively delegates through the platform and bootloader loaders for resolution, and then try the system classloader at the end, where it almost always will find your resource. – 8bitjunkie Feb 18 '20 at 17:03
  • I say "almost always equivalent" in the comment above because it is highly likely that `this.getClass().getClassLoader()` will return an instance of `jdk.internal.loader.ClassLoaders$AppClassLoader` (System classloader) – 8bitjunkie Feb 18 '20 at 17:07