A "Resource bundle" for persisting other then localization data - java

I need system similar to ResourceBundles except that I will not use it for localization. Basically, I need to store several versions of settings. One version of that settings is String-to-String map, that can be represented by Properties file. These settings versions must be easily persisted to file system inside application .jar (alike PropertyResourceBundle).
The idea is to have different versions of application settings (settings profiles), represented by key-value pairs of type string, that can be chosen from at application start up based of user decision. Again these are not language versions so ResourceBundle (according to its javadoc) is not the right way to implement it.
Any easy way how to do that without implementing the whole think myself? Please do not suggest third-party it should only use Java SE classes.
Edit: I forgot to mention one important detail. It would be hard for me to get stream like this: Thread.currentThread().getContextClassLoader().getResourceAsStream("/your/resource/here");. That is because the project that would contain properties file is compiled by Ant and used as a dynamically loaded library in different GUI projects that actually run. I might have all properties files in fixed project folder but since Thread.currentThread().getContextClassLoader() returns context of GUI project and I do not know where in that project was the .jar with property file placed by Ant I do not know what to use as "/your/resource/here".

I might have misunderstood the question however seems to me you can easily do something like this:
InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("/your/resource/here");
Properties prop = new Properties();
prop.load(inputStream);
This will be safe in a Java EE environment as well and you can call you anytime you need if you want settings to change.
Update: as long as the resource is on the classpath you should be able to find it without knowing the full path of the resource as well.

Related

Java - how to make a library I made use config values

Long story short, I'm making a java library that requires several 'config values'. Currently, I'm just using a config.properties file in the root directory and reading from it, but I don't see how that can work with a distributable jar file.
I've thought about making these config values parameters to a constructor of a class in the library, but there are too many values- it just doesn't seem like the correct way of doing things.
Essentially, I just need some way that a user of my library can just use the jar file, but also have the ability to change several configuration values that affect the function of the library.
If it makes any difference, I'm using maven to build my project.
Thanks in advance.
(Assuming you are just working in JavaSE, as Java EE has other configuration mechanisms.)
A pattern is to create a singleton class in your jar that provides configuration to the other classes. Which is reads default values from the property file in the jar. Allow the caller of the jar to override properties by setting them as system properties.
In the java doc for Property class there is a constructor to provide defaults and overrides and get the 'net' properties.
Giving the caller the option specify a property file by giving a file path as a system property.
Log4j and java.util.logging work of like this. Reading through there config documentation will help explain.
I will split your question into two parts and then answer each part separately.
I've thought about making these config values parameters to a constructor of a class in the library, but there are too many values- it just doesn't seem like the correct way of doing things.
For the part of your question I have quoted above, see the accepted answer (written by me) to the following StackOverflow question: How to handle large number of configuration parameters across a program conceptually?
Essentially, I just need some way that a user of my library can just use the jar file, but also have the ability to change several configuration values that affect the function of the library.
It sounds like your configuration file will contain N variables, and a user might want to customize the values of, say, just 2 or 3 of those variables. If N is relatively small, then it will probably be okay to use an either-or approach to configuration:
either the user provides a configuration file containing values for all N variables (the location of this file might be specified via, say, a system property, an environment variable, or a parameter to the constructor of your library);
or your library uses a "built-in" set of default configuration values, which I suggest you place in a properties file that you bundle into your library's jar file and then access by calling ClassLoader.getSystemResourceAsStream().
However, if N is large, then you might want your library to provide and semantics for configuration variables:
your library uses a "built-in" set of default configuration values, which I suggest you place in a properties file that you bundle into your library's jar file and then access by calling ClassLoader.getSystemResourceAsStream(). This provides default values for all N variables.
and your library loads an (optional) user-specified configuration file that might contain anywhere between 0 and N variables. The values of the user-specified configuration variables are used to override the built-in default values.
Obviously, you will need to implement the and logic within your library, but that is really just a SMOP (Simple Matter of Programming). Perhaps the simplest way is to iterate over the entries in the user-provided Properties object and copy them into the Properties object that contains the default values. In this way, the user-specified value will override default values.

Best way for storing Java application name and version properties

Using Eclipse IDE.
I need to store my application's name and version as they are used by the app itself.
I could hard-code them as static final fields somewhere in the codebase. A better solution I know about may be storing them in the manifest file distributed with the application JAR.
Storing these properties in the manifest file feels better to me, but the problem is that the properties (obtained via Package methods) are not accessible during the development phase - running/debugging from IDE.
Is there a way to define them in Eclipse Run/Debug configurations? Is there a better way of storing such pieces of information. (I can also imagine using the Preferences API, although they are not "preferences" per se).
Thanks.
Use properties file. Here is a good start: http://www.mkyong.com/java/java-properties-file-examples/

Accessing properties from application.properties in a non Controller class

http://www.javadb.com/using-a-message-handler-to-alter-the-soap-header-in-a-web-service-client
In the above mentioned example we have hard coded TestUser(username) and TestPassword(password) in the message handler class.I want to externalize these values.
After some research I was not able to implement #Autowired and #value .Please help me out with this
If your .properties file is saved somewhere on the local hard-drive and it is one of the KPL (Key Project Locations), you can simply do this:
Properties propObj = new Properties ();
FileInputStream fis = new FileInputStream("relative path to your file");
propObj.load(fis);
Once you do this, simply use getProperty() or setProperty() to access/mutate desired properties. There is also another way to use the loadFromXML() method if your choice of file is an xml file. I hope this solves your problem because it sounds like you simply having trouble to load a file regardless of being in a controller class. If I am right, then you will find endless examples online that tells you to do merely what I wrote above :)
When using things like #Autowire remember that you have to annotate before the beginning of the target class with #ContextConfiguration("location_of_file.xml"). Getting the correct relative path may be a bit tricky when specifying an applicationContext file. See here and follow other links to find out more about this.
BTW one thing you have to remember that application properties are somewhat internal to an application and for this reason, they are set in a .properties file outside the source files so that it can be run without changing source code (correct me somebody if I am talking bollocks!).
If you are using build automation tools such as Maven or Ivy, there is a way to make sure that your application properties are set using the a) POM and b) applicationContext.xml files. In this way, the application is even more decoupled from breaking down in case a relative path doesn't work out to be the some on a target computer. If you want this, you have to be careful about setting the filters in POM. I haven't personally done this by hand, but we were working on a project a few months ago when a colleague of mine set the filer in front of me. I remember this because everything was failing due to incorrect filter setting. Sorry, but you have to find it out yourself using uncle Google!

Internationalization - listing and adding languages

I'm making an application in Java. This application can be internationalized using ResourceBundles. I want to allow user to choose the language that he want to the application have. And there's a question: how to list available languages for the program? I don't want to use Locale.getAvailableLocales(), because I don't know if the app's got a .properties file for the chosen language. There's also the second question: can I add an ability to add additional language files outside the .jar file? And the last question: is there any better internationalization solution?
Regards
You could just store a fixed list of supported locales in some constant of your application. If you need to make this dynamic, I see two solutions:
use a properties file listing the supported locales, and load them from this properties file at startup.
iterate through the available locales (or languages), try to load a corresponding bundle properties file (using Class.getResourceAsStream()), and consider that the locale is supported if you get an InputStream, and not supported if you get null.
You could let the user add a bundle by putting some directory in the classpath, in addition to your jar. Drop the properties file in this directory (respecting the package hierarchy), et voilĂ .

Possible ways to abstract away hard-coded path-names for properties file in java app

I'm trying to bind in a third party app to our project but have discovered that the unix paths of their property files have been hard-coded into several classes. It is probably possible to make minimal changes to their setup, so my question is: what are the possible (and quickest) ways to achieve this? The third party app uses neither ant nor spring, but just a build script that compiles the code into a .jar that is called from the command line.
You could read the properties files as resources. Then you only have to put the directories containing these files into your classpath.
You haven't actually said what you want to achieve. Would your application determine some paths and pass them to third party app via an API? Would something in your environment (for example a command line argument) specify the location of the files?
I would first refactor their code so that I know for certain that any hard coded strings are held in one defined place. So if for example they have
readProperties("/usr/thing/propertyFileXxx.txt");
or
static final String PROPERTY_XXX = "/usr/thing/propertyFileXxx.txt";
readProperties(PROPERTY_XXX);
I would first consolidate to a single accessor for the properties
readProperties(PROPERTY_XXX_ENUM);
So now we have a well-defined single piece of code that determines where to obtain the properties of each type and a specific list of the types of properties.
Then we need some controllable way to define the set of property files to be used at run-time. I have used the idea suggested by #tangens of loading the properties as resourcees from a specific directory added to the classpath.

Categories