Arron & Jan,
I think you both are saying pretty much the same thing - with two points
of contention:
1) Who has the flow of control and call back on the other the
common/specific
behaviour.
Jan's
distribute (URL url)
method is really the pretty much the same thing as Aaron's
validateDeployment(URL, EAR-POJOs, WAR-POJOs)
the difference being the former gives control to the specific processing
and calls will be made to access generic processing. The later has control
with the generic processing and calls are made for specific information or
steps.
I think the reason that I like the former better, is that a) it is more
flexible and b) it can be called directly from the deployment controller.
I think it should always be called from the deployment controller, so that
we have the same handling for deploying a simple WAR as we do deploying a
WAR from within an EAR.
One of the use-cases we have is having multiple WebContainers deployed and
needing to workout which one to use to deploy a particular WAR. The way that
was intended to work is that the deployment controller would call each
deployer in turn saying "can you deploy this". It is the webdeployer
itself that will examine the DD's to work out if this webapp is for it.
So for this to work from the EAR deployer, it needs to use the deployment
controller to deploy the WAR's - rather than calling a specific webdeployer
directly.
Thus I think there is a case for the EAR deployer using the generic
APIs to call deploy the war, rather than calling it directly. Of course
it would have to make the ear DD's available to the deployment context
as Jan suggested.
2) Is the API generic or webapp specific?
Aaron has suggested
validateDeployment(URL, EAR-POJOs, WAR-POJOs)
If we combine the EAR-PJO and WAR-POJO into a DeploymentContext and
make validateDeployment a standard method called by the DeploymentController
then I think the two approaches are getting to be pretty much the same thing.
For more flexibility we could change this method to just deploy or distribute
and what Aaron suggests as
- for each web app in EAR:
- common deployer calls WebContainer to validate a web app,
- common deployer gets web MBean class from WebContainer
- common deployer creates web app MBean w/class & ObjectName provided
- common deployer sets properties on web app MBean
- common deployer tells web app MBean to generate custom code
becomes:
- for each web app in EAR:
- ear deployer calls deployer controller with it's deployment context
- deployer controller calls deploy on EACH Web Deployer
- Web Deployer examines DDs to work out if it can deploy this war
- Web Deployer calls common deployer to create web app MBean
- common deployer sets properties on web app MBean
- Web Deployer calls/returns to common deployer
- common deployer tells web app MBEan to generate custom code (what
is
this step anyway???)
A few more comments in-line:
Aaron Mulder wrote:
I'm arguing to split it up, so we do much of the common reusable
tasks in a central deployer and then dispatch to a specific deployer for
the truly custom details.
I think you both are saying that. So it is just the contract and the
path between the common and the specific we need to agree.
1. JSR88 deployment lifecycle vs geronimo hot deploy lifecycle
My feeling is that distribute can be done nearly entirely by the
common code, with 1 or 2 calls to the WebContainer.
That should be able to work the other way, with the web deployer doing
the deployment with 1 or 2 calls to the common code. I think there
is a case for the increased flexibility and generics of this approach.
Let's look at the
case of an EAR. Something needs to set up a series of ClassLoaders,
create one MBean for the EAR and another per module, validate all the
modules, and generate container-specific classes. There are a number of
steps invokving Goals and Tasks and Plans. I think the application
deployer could do everything listed above, with calls to the WebContainer
to:
- get the AppModule MBean class name (to use for a createMBean task)
- validate the application (given URL, DD, etc.)
- generate container classes (which I think amounts to precompiling JSPs
in the case of a web container)
If there was other web-specific logic, it would presumably happen
in the postRegister event on the application MBean. I think these same 3
steps would work for implementing "distribute" for every container type.
Most of the container-specific work seems to be in "start", which is
implemented by the container-specific app module MBean anyway.
2. typed deployers
the central deployment mechanism should only be responsible for
detecting things to be deployed, and arranging for distribute(),
start(), undeploy() or whatever to be called on the appropriate
deployer. Typed deployers are necessary because the things that are
being deployed are different. Sure, they might go through a certain
amount of common steps, and these can be abstracted for re-use within
each deployer, but it does not follow that therefore there should only
be one deployer for everything. For example, the web deployer, and only
the web deployer, should be responsible for determining such things as
the context path of a web application. This is very webby specific and
the natural place for this is in a web module. The information that is
used to determine that path can come from many sources: the name of the
directory or war, a tag in an application DD, or an override in a
geronimo-web DD, but the algorithm for choosing is specific to web
deployments only.
I agree with the spirit but potentially disagree with the example.
I do not believe that the application deployer should instruct the web
deployer on how to set up a servlet context or something like that. As
above, though, I think it can take most of the "distribute" work off your
hands, except for a couple container-specific callbacks. And startup is
in your court anyway, thanks to JSR-77.
As far as the context root is concerned, I don't want the web
container groping for content outside the web app -- the last things we
want is inadvertent dependencies where the web container penetrates its
interface to root around in the guts of the server or the application.
Something has to grope through all the DD's and work out the context path.
That is completely webapp specific logic and so it should be in the
webapp deployer.
So I thought it would be easy enough for the common deployer to do that
calculation for you (after all, it has the EAR DD, the file name, etc.).
But it doesn't *have* to be done that way -- we could instead pass the EAR
DD POJOs to the web container along with the WAR DD POJOs and let you do
the calculation yourself.
I think this is the solution Jan was suggestion. That all the DD's get
passed in a DeploymentContext to the specific Deployer. It is it's
job to grope about all those DD's and resolve any configuration such as
context path that can come from multiple sources.
So I think the way forward is for:
Aaron - can you think how to cast your proposal in terms of generic
rather than specific APIs, such that the Web app deployer (where ever that
may be) will see the same style of calls for a WAR in EAR deploy as it
would for a direct WAR deploy.
Jan - can you look at you current code and give more details of the
steps & process that could like be given up to a common deployer.