Hi folks,
we have a workable solution for moving around 40+ configuration files
and different database configurations - but it might not fit your needs
and might be overly complex ... :-)
Some background information
=================================================================
+) the backend library requires around 40 XML configuration files to
start all of its 100+ services
+) the web frontends come with their individual XML configuration files
+) each frontend might be deployed to different environments, e.g.
staging or production environment
+) each environment uses its own database settings
+) a frontend WAR does not contain the configuration files but - they
are stored in zip (attached artifact). To be more accurate the zip file
contains multiple zip files where each zip contains a set of
configuration files used for a web deployment. During a deployment the
WAR is unpacked and the desired configuration is manually copied to WEB-INF.
How it works
=================================================================
We wrote a maven plugin to assemble arbitrary configuration files using
three configuration levels
+) the backend base line configuration
+) the customer specific configuration
+) host specific configuration (e.g. development, staging or production)
The configuration files are copied in the correct order (from general to
more specific) to a target directory. During the copying we expand any
macros found in the configuration files using ANT copy filter. The
property file being used for the expansion is concatenated in the
correct order regarding their configuration levels and database properties.
In short the plugin build a set of configuration files for a given
configuration path (e.g. "backend/customer/staging") and a given
database (e.g. "[EMAIL PROTECTED]").
For a frontend release we build multiple configuration paths whereas
each configuration is zipped. The resulting zips are zipped into a
single *-server-configs.zip which is attached to the frontend and
therefore uploaded to the repository.
Conclusion
=================================================================
+) the solution might no be generally applicable (since our requirements
are very complex) but it contains a few lessons learned aloong the way
+) making it work was non-trivial but most of the magic is hidden in a
parent pom (and we are still improving it)
Cheers,
Siegfried Goeschl
BTW - thanks to Markus Strutzenberger (aka Mark Struberg) for making
this magic possible
Vincent Massol wrote:
On Mar 16, 2007, at 1:20 PM, Kenney Westerhof wrote:
Hi,
Vincent Massol wrote:
Hi,
I've never found a good answer to this use case so far so I'm
curious about how others have implemented it.
Imagine a project that generates a WAR. This WAR contains a config
file (say in WEB-INF/classes) that configures connection parameters
for the database.
Now imagine that your project wants to support several databases and
you want the ability to build for a given database.
I see 2 options:
Option 1
-----------
* Use filtering
* Use profiles to set the values for the different databases
Issues:
* In order to differentiate the generate WAR file name you'll need
to use <finalName> but the value set there won't be used for
install/deploy which means that the WAR files users will see will
always be the same.
You could use the buildhelper-maven-plugin or the assembly plugin
to attach the artifact with a classifier.
You can also configure the jar/war plugins with a <classifier> element.
ok will check all these out, thanks.
Idea for future:
* It would be nice if Maven had a <classifier> element under
<project> so that it would be possible to generate an artifact with
a classifier.
That's not an option. The pom is shared between all artifacts,
both primary and all secondary attachments. The main artifact is always
without a classifier.
Option 2
-----------
* Create one module per database, under a parent module
* Create profiles in the parent module to conditionally include the
<module> to be built
Issues:
* Very heavy (one module per database) especially when the only
difference between the generated artifacts is only 3 lines in a
config file
* Need a way to share common configuration between the modules, in
order to prevent duplication. For example if the config files only
contains 3 lines that are different for each database and there are
100 lines in total, you don't want to duplicate the 97 lines in as
many modules as you have databases
What do people do? Is there some plan to support this use case in a
better fashion in the future?
This is typically solved in several different ways, depending on the
role
a person has in the team. Standard j2ee practices etc. recommend a
'deployment manager'
to either edit WEB-INF/web.xml before deploying, or as an alternative, a
'system manager' will provide you with the name of a JNDI Datasource
configured
in tomcat's server.xml (or whatever container is used). This latter
approach is best since it won't require any modifications to the war.
You're just pushing the pb as Tomcat would need to be configured too,
so the WAR would be the same (good) but the module that generates the
container zip/install would have the same issue. And if we tell the
users that they need to have a correct configuration then it's not good
enough. What I'm trying to provide is an out of the box solution so
that users download a zip, they expand it and it just works. Of course
there are still some dependencies to the environment like the need for
an OS installed, a JVM, etc but the idea is to have something as easy
as possible to use OOB.
Also we're not using any JNDI server and to be completely generic we
would need to a Generic Configuration Server used to serve
configuration data to the application. But again this pushes the pb to
this Configuration Server app.
In the case of embedded databases or other circumstances, some other
solutions could
be:
- split the configuration into 2 files: the common file that's the
same for each 'classifier',
and a database/environment specific file. The modules would then
only contain
the environment specific file
Right. This requires some heavy lifting for the app I have in mind and
is a little bit less nice for end users as right now they only have to
know about a single config file and they'd need to know about several.
- create the environment specific file using filtering and maven's
profile mechanism
Sure, but that still requires a solution for the common parts.
Something like resource injection (I need to check if the remote
resources plugin can do something like this)
- package up just 1 war with a property file for all possible
environments.
Specify a system property or a configuration file or JNDI property
that contains the name
of the type of environment, and let the webapp load the appropriate
property file.
Downside is that you cannot use the automatic mechanism of the db
provider to load the property
file, but you have to supply it in code.
Yep this was what Jeff suggested too but again it's less nice for the
end user.
I'd go with either profiles for different environments, or just use
settings.xml
with some properties that need to be configured (so that developers
themselves
can choose wheter 1 profile is sufficient, or create multiple
profiles for different
environments).
If the only data you want to change is database settings, I'd go with
a static JNDI name.
Thanks Kenney for these options. I still don't think we've reached the
ultimate solution with all these options. For example with a pure Ant
solution it's possible to come up with a better build strategy that
doesn't impact the end users. I'd love if Maven could provide a way to
do that too in an easy manner.
I'll investigate the options you provided under option 1 and revert
back here if I find something useful.
Thanks again for your help
-Vincent
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]