I'd ask you to set aside traditional thinking and try this out for a bit.
When you write code, you edit a couple of source files, compile it, fix
the typos, build a jar, test it, decide its good enough and commit the
change. After doing this a few times you decide its good enough and do a
release, taking the jar file you built and saving for posterity. You
then do it all over again.
If you're doing this with Maven, it spells out the difference between
the jar you are working with (a SNAPSHOT) and the jar you release
(something with a version number).
Sound familiar?
In a large production environment you do the same kind of thing with
system configurations. You set up a system the way you want, check that
it works, beat the snot out of it (aka stress testing or benchmarking),
see how/when it falls over, tweak the config and repeat until it you're
happy, then document it, have someone else try the change in your
staging environment, check it still works, then beg the change control
board to let you move it to production at 3AM on a Sunday morning. You
then cross your fingers and hope it really works.
A bit different from changing things on a desktop machine or the box
that runs the family website, but not unrealistic and the problem the
architecture was trying to simplify.
[[ to avoid a disgression, is Geronimo ready for this? Who knows; in the
end the people doing such things factor in the risks associated with any
software no matter how mature and they will make up their own minds ]]
The idea behind the configuration bundles is that they are pre-wired
sets of closely coupled components that co-ordinate to perform a
specific task. A single bundle is *not* meant to represent the entire
system assembly - the current o/a/g/Server is an abberation caused by
problems in the classloader model (described elsewhere) not example of
"best practice."
The purpose of a bundle is to allow a knowledgable person to, for
example, pre-wire a web container in a way that allows other people to
use it just by defining a few characteristics. So, for example, someone
can go to a repository and find, for example, a pre-wired version of a
Jetty bundle pre-configured for 100 concurrent users at 95% static
content with a typical dynamic reponse time of 500ms when running on an
Acme-4000 Linux machine.
So why does this need to be immutable? Because if you are pulling these
things from a catalog then you need to know that you're going to get
what you expect and not some version that someone happened to tweak but
just forgot to change the name.
It would be like having several jar files out there called
log4j-1.2.8.jar that were actually different - a recipe for chaos. BTW
one reason bundles are JAR files is because it's dead easy to sign them
so that you can tell if they have been tweaked.
Now, just as in the code development example I gave at the top, these
kind of pre-packaged bundles are also going to go through a development
process. One reason we didn't version stamp the configIds in the current
assembly is that until now all our configurations have really been in
development and it didn't make sense to be dealing with new versions all
the time. It probably would have been clearer to id them as e.g.
o/a/g/Server/1.0-SNAPSHOT but I guess that's water under the bridge now.
So, in an ideal world, your user below would just pick a suitable
pre-built bundle out of some repo and be happy with what it does. If it
doesn't quite do what they want or nothing suitable can be found, they
start by building and tweaking my/web/Container/1.0-SNAPSHOT, iterate it
a few times and then finalize on my/web/Container/1.0.
The problem is identical to a developer not filling up their Maven repo
with trivially different versions of a jar they are working on (which is
why Maven has SNAPSHOTs in the first place).
To pick a bad analogy, we're trying to do with server configuration what
Maven did for builds. No, I don't mean trying to make it slow and take
forever to start. We're trying to simplify the administration process by
allowing a admin to choose from a re-usable set of pre-optimized bundles
rather than having to do it all by hand, in the same way Maven uses
plugins to replace manually created ant scripts.
It's different. It's unusual. It takes some getting used to.
But it might just work.
--
Jeremy
Aaron Mulder wrote:
For my part, I'm not convinced that it makes sense for
configurations to be immutable. I think the export/import feature would
be nice -- "I finally got my web container configured 'just right', now
let me export it and load it into my cluster of 30 boxes". I wouldn't
even mind giving each configuration a unique hash or something such that
we could eventually down the road add a feature where you export two
related configurations, and one refers to that specific build of the
other. Or even having an immutable flag on a configuration such that once
you've marked one as immutable it refuses to change in the future.
But to tell me that properties of a configuration shouldn't ever
be changed, or that GBeans shouldn't be added or removed at runtime and we
should create new child configurations instead... unless I'm
misunderstanding you, that just doesn't work for me. I can't imagine
someone customizing their web container and then after a few revs they try
to load or unload or export it and discover that they now have
configurations "Server", "Server HTTP v1..v5" "Server HTTPS v1..v3"
"Server AJP v1 & v2" "Server Keystore v1..v4" "Server accept thread pool
v1" "Server JSP Compiler v1..v3" "Server request log v1..v5", and so on.
Much better IMHO to let them alter the "Server" configuration to their
heart's content, then let them export it or flag it as locked if they want
to preserve a snapshot of that state.
Thanks,
Aaron
On Mon, 25 Jul 2005, Jeremy Boynes wrote:
Configuration bundles are meant to be immutable so you shouldn't be
adding things to them at runtime. Think of them as being similar to
library jars or other maven artifacts - things would get very confusing
if you started adding classes into them as part of a build. This allows
the configuration to be identified by its ID in the same way the
artifact id identifies a dependency to maven.
Configuration bundles have attributes (currently modeled by exposing the
GBeans they contain which is problematic) which pertain to the location
in which they are being used. The *default* values for those attributes
are contained inside the bundle; the instance value is set by the
environment.
There are some implementation issues in Geronimo today (short cuts taken
for expediency) which obscure some of the subtleties of this model. Some
of these relate to classloading (the issues on the packaging thread),
others relate to GBean persistence.
I'll give a couple of examples which I hope highlight a couple of the
issues.
The first anti-pattern is that configuration ids are not unique - we
reuse them for different configurations. For example, although Tomcat
and Jetty based servers are quite different we use the same "unique" id
(org/apache/geronimo/Server) for both. We also reuse ids across versions
so it is impossible to tell if an application deployed against
org/apache/geronimo/Server was built using M1, M2, M3 or HEAD. It is
like only ever compiling against SNAPSHOT dependencies.
Secondly, if configurations are immutable then you should not be able to
add GBeans to them at runtime (that would be mutating them). So how do
you add a network connector? The simplest model is to separate the web
container from its connectors and build them as separate bundles (one
for the container, one for each of the connectors); if you want to add a
new connector you add a new instance of e.g. the HTTPS bundle.
Finally, there is the issue of instance properties - things in the
environment of where a configuration is being used that need to override
the default properties that is has. For example, the default for the
HTTP connector bundle might be to listen on port 8080 but on this server
here it needs to be changed to be 8888. Right now we do this by mutating
the configuration installed in the store which is problematic. Instead
it would be better to associate the state with the runtime and, after
the bundle was loaded but before it was started, inject those local
values into it.
There's a fine line between when you want to override values on a per
instance basis and when you want to define a new configuration for with
those values as defaults. There's no right solution to that but I think
the type of installation plays into it:
* for a desktop development environment or single server installation
then you are better just overriding properties as needed
* for a clustered environment or large scale deployment then you are
better defining reusable bundles that can be easily moved where/when
they are required
As Geronimo starts being considered for larger installations let's not
forget what the original config system was designed to do.
--
Jeremy