Java - application configuration
-
So I have this Java program--a servlet, actually--that will be running on more than one machine. Each instance needs a single piece of information (a URL) that will be different on each machine. What's the simplest/most straightforward way of doing that? I thought asking here would be easier/faster than trawling SE or trying to figure it out myself.
What's actually going to differ is which host the URL is called on: dev needs to call a dev machine, QA, a QA machine, and so on, although the list of machines isn't likely to ever change. I just don't want to have to put the URL (the hostname, actually) in the source.
-
Is this for a database connection, the url of the box you're running on, or an external URL?
I ask because the three would probably each be handled differently.
-
External URL the servlet will communicate with. Something similar in concept to an INI file is the gist of what I'm looking for--on servlet startup, obtain the hostname, so I can call a fixed URL on that hostname.
-
I know nothing about Java, but I'd say a text file.
-
That makes a certain amount of sense, but I was wondering if there was a specific API. the class java.util.Properties seems like it might be useful but I don't know if it will be the simplest/best thing to use (for example, if it creates a binary file, that means I have to write another program to initially create the file for each server, as opposed to just opening up a copy of Notepad.
-
java.util.Properties are just plain text key-value-pairs usually of the format:
foo=bar
-
I know for a fact you can store things like URLs in the webapp's web.xml. However, some application servers won't let you modify that in the deployed application (or won't recognize the changes).
Sooo.... it might be better to modify a Properties file instead.
Properties files can be placed in the web app's
WEB-INF/classes
directory.In order to read files from a web application, you must use one of the
getResourceAsStream
methods.For instance, if I were trying to read
myservet.properties
from a class namedMyServlet
...InputStream in = MyServlet.class.getResourceAsStream("/myservlet.properties"); Properties props = new Properties(); props.load(in); in.close();
Edit: Forgot to close the InputStream above. Fixed now.
Incidentally, a properties file just looks like this:
key=value anotherkey=anothervalue
(I had to look in my app's log4j.properties file to get the syntax for the file's contents, you'd think Oracle would document it somewhere)
-
You can always set a environment variable and pass it as an argument when you start Tomcat(?)
$ java -Denv=qa bla bla System.getProperty("env");
-
java.util.Properties are just plain text key-value-pairs
Cool. I spent about 3 minutes looking at the javadoc and wasn't sure.
I know for a fact you can store things like URLs in the webapp's web.xml. However, some application servers won't let you modify that in the deployed application (or won't recognize the changes).
We'll be running Tomcat 8.
It sounds like Properties files will be the way for me to go, as I can just create a subdir in our source tree[1] for each server, and stick a properties file in each directory, with the proper data in each one, although the other way should work too. (How do you use web.inf? I'm still kind of new to the servlet world. I was planning on sharing a single web.inf along with all the different properties files, but if I can reduce that to "just one web.inf per machine and no properties files" that might be even better.)
[1] Getting source control into this company is a lost cause.
-
Hmm. This is Windows, and we're using the "start Tomcat as a service" so I assume you'd set a Windows environment variable instead, but that could possibly work too.
I'm liking the idea of using a file a bit better as that will simplify installation/administration.
-
I think this will work for using the web.xml. Most of my Tomcat experience has been fighting against trying to get the remoteAddress valve thing to restrict access to only allow connections from localhost. Don't ask.
-
This post is deleted!
-
Just realized my last post had Context Params in web.xml with the code to fetch Init params. Whoops.
What @MathNerdCNU said for init-params.
Context Params are similar, but bound to the servlet context instead of a particular servlet.
They look like this in web.xml:
<context-param> <param-name>key</param-name> <param-value>value</param-value> </context-param>
For an
HttpServlet
, you can fetch Context Params usingString value = this.getServletContext().getInitParameter("key");
Classes that just implement
Servlet
instead ofGenericServlet
orHttpServlet
will need to do this:String value = this.getServletConfig().getServletContext().getInitParameter("key");
-
Oh, that looks like it'll be perfect for my needs. Thanks.
-
Context Params are similar, but bound to the servlet context instead of a particular servlet.
I don't really understand contexts yet. In this case, there will essentially only be one copy of the servlet on each server, so init-params will probably work fine for me.
-
If you're extending HttpServlet, you can call
this.getInitParameter("key")
and skip thegetServletConfig()
Yay convenience methods.
-
If you're extending HttpServlet
I am. It seemed to make more sense than extending the base class.
Yay convenience methods.
Indeed.
-
I am. It seemed to make more sense than extending the base class.
@CodingHorrorBot, what am I doing if I implement
Servlet
instead of extendingHttpServlet
?
-
@powerlord Is Doing It Wrong™