Search code examples
javajakarta-eeresourcebundle

Loading Property file from FileSystem in a Java EE application



I am using EJB 3.0 and CDI to develop a java ee application which will be deployed in Websphere application server. I have a requirement to have a property file from which i read certain configuration parameters and this property file should reside in the filesystem of the host system where my code will be deployed. The base path ( directory where the property file will be placed ) for the property file is configured as a Name space binding String resource in Websphere application server.

Currently i have coded a Utility class to retrieve and use the property file which looks as below.

 @Singleton
    public class AppPropertyUtil {

        private static Hashtable apppProperties;

        @Resource(name="jndi/basePath",lookup="jndi/basePath")
        private static String basePath;

        private static final Logger LOGGER = LoggerFactory.getLogger(AppPropertyUtil.class);


        protected void loadPropertyBundleFromFileSystem(String path)
        {
            InputStream inputStream = null;
            Properties properties = null;
            try {String fullPath=basePath+"/"+path+".properties";
                LOGGER.info("Property file path : "+fullPath);
                inputStream = new FileInputStream(new File(fullPath));
                if (inputStream != null) {
                    properties = new Properties();
                    properties.load(inputStream);
                    LOGGER.info("Properties loaded");
                    apppProperties = (Hashtable)properties;         
                }
            } catch (FileNotFoundException exception) {
                LOGGER.error("Cannot read property bundle ",exception);
            }
            catch (IOException | IllegalArgumentException exception) {
                    LOGGER.error("Unable to loadproperties ",
                            exception);
                }        
        }

        public String getProperty(String key)
        {
            if(apppProperties == null)
            {
                loadPropertyBundleFromFileSystem("AppProps");
            }
            Object value = apppProperties.get(key);
            if(value != null){
                return (String) value;
            }
            return null;
        }

    }

But having the @Resource annotation will mandate that the AppPropertyUtil class be injected inside any class that wishes to use it. So, I will not be able to use this in any POJO classes which are not managed.

Please help me understand whether this is the best approach to go with for the above requirement or could this be improved. I would also like to make the getProperty method and loadPropertyBundleFromFileSystem method static to have it being used from a static context, but it is not possible as the class should be injected to be used.

Thanks in advance


Solution

  • Ideally, you shouldn't need to access to your class from any POJO. Use design patterns and separate your concerns. Use your class as a service to load up your property file and serve out a Map or Set of it's contents. POJO Models shouldn't care, but your other classes can read that map/set of properties and pass them to your pojo's or other classes which need it but don't have direct access to it.

    The other option is to remove the @Resource and make this just a plain old util class that you pass in the filename to read in it's constructor, then when you call getProperty, you do what you do to check to see if it's been loaded already, if not, load it.

    Wrap that in a factory that supplies the @Resource parts and it keeps your EE code from bleeding into your other jars (utils).