What are the best practices here?
Okay, so I have an application. It's written in Java, compiled to a JAR file. It's compiled, tested, packaged, and distributed using Maven, because that's the new hotness. The program has options that need to be set for it to run correctly. There's more than 3 options.
(For simplicity, I've removed all the details, because if I go into nuances your eyes will probably glaze over)
What is the "best practice" way to do this? My first attempt ended up with, after about 2-3 days of fighting with the system, a config file inside my maven repo but outside the jar that loads correctly, but that means the end user has to go find their maven repo and edit the file there, and that doesn't feel right. I could hard-code a path like C:\Program Files\Program Name\Config.config, but it'd be the only thing there (because the JAR lives in the maven repo) and how do I get maven to install it and what if that fails? I could put a huge string of command-line options but that's hardly user-friendly at all.
What's the expected paradigm here? This has GOT to be a solved problem, it's 2014....
can the options have sensible defaults?
i.e. can it be made to work in general, and the options tweaked, or are the options breaking settings where nothing works without changing them
Yes, the config file I ship with works, but might not do what is needed. In actual practice the usual way this will be launched can have a fancy GUI to set the options so the user doesn't need to hunt down the file, but this has been bugging me ever since I settled on this approach, I feel like I'm missing something obvious here.
In .NET land, I'd presumably be shipping with an installer and it would install to a known location (program files) and that's where the user would expect to go to edit any config files. Do people expect to go into their maven repo to edit configuration details?
If this was a .Net project I'd use a .config file with user settings (so they're editable from Settings.Default) and make an options screen for editing the settings. That way the user doesn't need to fudge around with the config file manually. The .Net settings API is pretty good.
I don't know the java equivalent of this, but a cursory search led me to this: http://stackoverflow.com/questions/3784657/what-is-the-best-way-to-save-user-settings-in-java-application
If you can't set sensible defaults you'll need to make sure the user sets the settings on first launch.
I have no gui in this case. It's basically a library to be implemented in a command-line app, but it's kicked off from a GUI app (Jenkins CI) where I can and have set up a screen to select options. So it sounds like that's "correct".
Is it a command line application or a service then? Or something else?
EDIT: fixed typo (I should really learn to type, or stop having too much coffee)
See edit to previous answer
That sounds sensible to me.
I commonly use something like this:
String userDirStr = System.getProperty("user.dir"); java.io.File userDir = new java.io.File(currentDirStr); java.io.File configFile = new java.io.File(userDir, "config.properties");
This uses the current directory in most cases, unless you start your program by defining
user.dirto be something else. The latter can be nice when writing test code.
Hmm... I wonder what that'd do when the user running the software is Jenkins... maybe I want to pass in a command-line parameter and use user.dir as a backup, except that command line parameters confuse me when using maven.
How do you actually launch this program?
Do you have your own Jenkins plugin, or are you calling the program through yet another Jenkins plugin?
I also don't get what Maven has got to do with this all, so you might need to give more details about your whole setup. It almost sounds as if you are downloading the dependencies for a Jenkins plugin using Maven, then run the program using Maven as well.
Are you developing a plugin for Jenkins?
It almost sounds as if you are downloading the dependencies for a Jenkins plugin using Maven, then run the program using Maven as well.
Yes, that's exactly it. The program is the framework for some functional tests, which are in their own JAR/maven project and executed using maven surefire, so I'm just using the "execute a maven POM" function of jenkins to kick it off. Except I'm having it construct a config file on the fly using the "parameterized build" function so that the config file doesn't have to be manually updated every time.
Using surefire, you can specify command line arguments by adding an
<argLine>tag in your
<configuration>tag. This would let you have the config params in the pom. Would that solve your problem?
Would that be considered a better practice than a config file? I went for the config because the list of options was getting pretty long, but I'm not sure which methodology is preferred these days.
If you had a local service/daemon that needed some configuration, I'd suggest having an external GUI application for that. However, you're running inside Jenkins (i.e., it's really a sort of plugin for a web service) so I'm much less certain about the details. Probably have to have some sort of UI plugin screen (or sub-screen, if I remember the Jenkins config UI right) that builds the config document.
I've never needed this sort of thing directly myself, and so I don't know the details. My use of Jenkins has been to just run Maven builds (which I can make very complicated when doing particular types of application assembling and deploying) but that's a case where editing a complicated config file (the pom.xml) is the way you do it anyway.
The one piece of mandatory literal config might just be where the real config file is. Though that perhaps ought to be subject to a “reasonable” default too; that's the maven way…
It really depends on your usage which I am not sure I totally understand, but it sounds like you might be looking for something like https://wiki.jenkins-ci.org/display/JENKINS/Config+File+Provider+Plugin
However, if you intend for your project to be a dependency of other projects it might be best to have each project that includes your framework provide the config file on the classpath. That has the advantage of allowing you to do maven builds outside of Jenkins. IMO, I would go with this approach.