3
\$\begingroup\$

I am no newcomer to Java. One thing that confounds me is why it is so messy to load values from .properties files.

I have an application where, if the .properties file is found, then the value if found, should be used. And in any other circumstance, to use the default. (In the correct deployment, the server is run with sufficient permissions to engage with the socket listener 443, whereas in the development environment or any other environment where a person goes to the trouble to insert the .properties file, another port will be used).

The location of the file is com/foo/bar/webserver.properties in the in the same directory as the class file com/foo/bar/WebServer.class.

The content of webserver.properties is simply:

 listen=4444

Since this such a terribly simple function I would like to know if the community of reviewers sees a more elegant/succinct/secure/complete/correct way to load the value. I feel like I must be overlooking something basic for what feels like, to me, should be a one-liner more like the imaginary API:

    // set int value for key "listen", or else default value 443
    int port = Properties.loadProperties( "webserver.properties" ).getInt( "listen", 443 );

And here is my real code for review:

    int port;
    try ( InputStream webserverProperties = WebServer.class.getResourceAsStream( "webserver.properties" ) ) {
        if ( webserverProperties == null ) {
            port = 443;
        } else {
            Properties p = new Properties();
            p.load( webserverProperties );
            String listen = p.getProperty( "listen", "443" );
            port = Integer.parseInt( listen );
        }
    }
    catch ( NumberFormatException e ) { port = 443; }
    finally {}
\$\endgroup\$
  • \$\begingroup\$ Have you consider using xml de/serializing to load and save the properties? \$\endgroup\$ – tinstaafl Nov 26 '18 at 15:39
  • 2
    \$\begingroup\$ Java's Properties class is old, and it shows. It's also designed specifically to work only with String values. It sounds like it's not a great choice for the problem you've got. You might want to consider using a different abstraction or writing your own. It shouldn't be that hard to compose a Properties instance into the fluent API you're describing as your ideal. \$\endgroup\$ – Eric Stein Nov 26 '18 at 16:02
  • \$\begingroup\$ @tinstaafl, no I did not, because I am reading a single int value. I fail to see how that would simplify the operation, but I am happy to learn something from your answer. \$\endgroup\$ – Douglas Held Nov 26 '18 at 16:47
  • \$\begingroup\$ I realize your code only loads one property value. However your title indicates you may want to load more than one. It seems to in that case de/serializing would be more efficient. \$\endgroup\$ – tinstaafl Nov 26 '18 at 17:11
  • \$\begingroup\$ I think if I had many properties to read, I would write a Properties intermediary class with methods that would look very much like my code sample. And then, I think it would be appropriate. But, to only read a single int I think 12 lines of code is dubious. \$\endgroup\$ – Douglas Held Nov 26 '18 at 17:18
1
\$\begingroup\$

you could at least get rid of the if by combining the exceptions:

int port;
try ( InputStream webserverProperties = WebServer.class.getResourceAsStream( "webserver.properties" ) ) {
        Properties p = new Properties();
        p.load( webserverProperties );
        String listen = p.getProperty( "listen", "443" );
        port = Integer.parseInt( listen );
}
catch ( NumberFormatException|NullPointerException e ) { port = 443; }
finally {}

or ignore exceptions at all:

int port= 443;
try ( InputStream webserverProperties = WebServer.class.getResourceAsStream( "webserver.properties" ) ) {
        Properties p = new Properties();
        p.load( webserverProperties );
        String listen = p.getProperty( "listen", "443" );
        port = Integer.parseInt( listen );
}
catch ( Exception e ) {}
finally {}
\$\endgroup\$
  • \$\begingroup\$ Yes, I think the second option is good, and in fact in this case the empty finally{} block can also be omitted. Thank you. \$\endgroup\$ – Douglas Held Nov 28 '18 at 14:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.