Managing local files with Maven and SVN
I'm looking for a best practice for injecting local files into a project that are not being tracked with source control in such a way that the source-controlled version of the file is blind to the changes.
In particular, I have a context file with database credentials in it. I want to keep the raw "put your credentials here" file in source control, but I need to have that file filled out with the appropriate credentials for my development setup (or the production server, or what have you) without those credentials being pushed back into source control. Obviously, I can just edit the file locally and not check it back in. However, that becomes tedious over time, being careful that I don't accidentally check in the file with the credentials to the central code repository every time that I need to check a change in. An alternative approach would be to check in a "-dist" type file that each user would have to rename and edit to get the project to build at all.
I tried looking into Maven Overlays as that looked like it would require me to build a whole separate project for just my local credentials, with a pom.xml and a war file. That seems li开发者_如何学编程ke a lot of overhead for just a couple of files. What I'm really after is a way to tell maven "if the file X (which isn't in source control at all) exists locally, use it. If not, use file Y (which does exist in source control)." It seems like there should be a fairly automatic way to handle it.
Simple
I have done this in the past, it is very simple, have a single file for example default.config
that gets checked into version control, have another file called local.default.config
that is in your svn.ignore
file. Have Maven copy the local.default.config
over the default.config
if it exists, or have it copy both and your application look for local.default.config
and then default.config
if the first doesn't exist.
You can even use the same default.config
name and have the application look in multiple places, with your home.dir
as the highest priority, then some place else.
An ideal version of this will read all the files in some priority and use the last found property from all the files, then you could have default.config
with all your properties, and local.default.config
with only the few that need to change for your local configuration.
More Sophisticated Maven Oriented
Maven has multiple ways to get where you want to be:
- Use Maven
profiles
to enable and disable aproperty
that holds the file name you want to use and use the maven-resources-plugin to copy the file you specify in theprofile
. - Use the
filter
feature in Maven withprofile
drivenproperties
. - Use the maven-replacer-plugin to manipulate the file directly based on
profile
drivenproperties
- Use the maven-dependency-plugin and store your files in your local Maven repository and pull them down from their during the
package
phase.
profiles
are very powerful and a perfect fit for configuring Maven for different environments. I have a local
, dev
, qa
and release
profile in every pom.xml
. I set the local
profile to active by default, and pick the others as I need them with mvn [goal] -P dev
which will automatically disable local
and use the properties
specificed in the dev
profile.
More sophisticated SVN oriented
You could work off a local development
feature branch and only have your local configuration on that branch, and when you merge your code changes back to the trunk
exclude your changes to the configuration file from the merge. This is actually how I would do it since, we use Git. Branching isn't so painful in SVN that this isn't an option
I am sure there are other Maven solutions as well. Either way you solve it svn.ignore is your friend. And Maven profile
usage can be very powerful.
Is the Maven replacer plugin a solution for your need?
We use jasypt to encrypt our passwords within properties files read by Spring. The tool can be used without Spring as well. This makes it very simple to keep your properties files in source control.
If your issue is user credentials, then I would suggest that you use a test account for any automated tests that you run.
I think filtering may suit your needs. You can have a local.filter that is not checked in and prod.filter that is. You can use the prod.filter by default and substitute the local.filter based on a command-line flag or local profile that developers would need to use, but deployers would not.
精彩评论