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


Reply via email to