geronimo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Aaron Mulder <>
Subject Re: [webapp deployment] Progress (was Re: [Deployment] Application Deployment Status)
Date Tue, 07 Oct 2003 17:32:46 GMT
Just to kind of recap where we are (I think):

 - I favor a central deployer which delegates only where necessary
 - Jan favors separate deployers per module, with a common base class
 - We seem to be more or less in agreement on the API, whichever way it 
ends up being implemented
 - Gianny was going to put together some sample code

I think I'm fine going ahead with something more like what Jan is
proposing, though I'm still not convinced that it's the best approach 
(commentary below).  Gianny, are you still going to be putting out a 

In the mean time, I'm working on getting the JSR-88 implementation up to 
speed with web modules.  It's close, but not quite there (primarily, we 
need to be able to write the DD POJOs out to an XML file).  You can edit 
the geronimo-web.xml DD with the command line deployer, but not save it 
yet.  :)


P.S. What good is all this flexibility when we know we'll have exactly
EARs, WARs, EJB JARs, and RARs, and we need to specifically arrange
ClassLoaders across them, and there are hardcoded constants for those
module types in the J2EE 1.4 API?  It's not like you could/would just drop
in a new xAR archive/component type.

On Mon, 6 Oct 2003, Jan Bartel wrote:
> I am definitely in favour of a central controller, but not a central 
> deployer. The DeploymentController that we have now is the only central 
> entity that is necessary. In other words, something whose only task is 
> to notice that there are things that need to be deployed, undeployed or 
> redeployed. The DeploymentController needs to be able to support both 
> the geronimo hot deploy directory and also deployments coming from a 
> JSR88 tool.
> > 
> > 
> >>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.  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.
> In my reply to Gianny's email, I've said what I think is the biggest 
> weakness with the central deployer approach: that is the lack of 
> flexibility. To add support for a new deployable type, we'd have to 
> modify the central deployer code, adding yet more "if then else" clauses 
> each time. By keeping individual deployers (but that reuse common 
> deployment code perhaps from a baseclass) we gain a lot of flexibility. 
> For example, with individual deployers, we are able to hot deploy a new 
> deployer and introduce support for a brand new deployment type into a 
> running geronimo instance.
> >>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.  
> > 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'd much prefer that the interface contract to the deployers contained 
> the DD pojos (preferably as part of a DeploymentContext, but that is 
> covered in other threads), so that the individual deployer can extract 
> whatever information it requires. That allows for maximum flexibility.
> > 
> > 	Thinking back, I seem to have overlooked how the ObjectName will 
> > be generated.  Personally I would rather have standard application module 
> > ObjectNames no matter what container is plugged in, so I'd rather see 
> > "geronimo.deployment:role=WebApplication,instance=(unique ID)" instead of 
> > "jetty:...".  So I'd prefer to add a 4th method "getUniqueID" to the 3 
> > listed above.  But if you feel strongly it could just be "getObjectName" 
> > and you can construct a Jetty name instead.
> As Gianny has pointed out, JSR77 seems to have something to say about 
> acceptable names, so we'll stick to those. I just blindly followed the 
> naming precedent that had been set in the "hack" Jetty integration. Now 
> I know better :-)
> >>3. ear/war relationship
> >>wars can be deployed standalone, or bundled as part of an ear. In the 
> >>latter case, then some of the deployment information for the war is 
> >>contained in the deployment descriptor for the ear, and as you point 
> >>out, the classloader hierarchy needs to be established. I think this 
> >>should be handled as much as possible via the normal deployment mechanism.
> >>
> >>To that end, I suggest we augment the signature of the deploy, 
> >>distribute, undeploy etc methods with another parameter: 
> >>DeploymentContext. This context can contain deployment descriptor POJOs 
> >>or xml, or classloader objects or perhaps state information. Anything 
> >>that defines the context in which the deployment is taking place.
> > 
> > 
> > 	Well, I agree that we need to get more information to each 
> > container.
> > 
> > 	Let me propose a revised base WebContainer and WebApplication, and
> > let me know what you think.  I believe this should leave the bulk of the
> > "geronimo kernel"-specific logic in the central deployer, and the bulk of
> > the module-specific logic in the container, which seems to me like the
> > right split:
> > 
> > abstract class AbstractWebContainerMBean {
> >   // returns i.e. JettyWebApplication
> >   public abstract String getModuleMBeanClass()
> > 
> >   // validates the deployment and returns an ObjectName if valid
> >   public abstract ObjectName validateDeployment(URL, EAR-POJOs, WAR-POJOs)
> > }
> > 
> > abstract class AbstractWebApplicationMBean
> >   public void setURL(URL)
> >   public void setBaseClassLoader(ClassLoader/ClassSpace)
> >   public void setEARDeploymentInfo(EAR-POJOs)
> >   public void setWARDeploymentInfo(WAR-POJOs)
> > 
> >   // will be called during distribution process; can precompile JSPs
> >   public abstract void generateContainerClasses()
> > }
> > 
> > 	So now the sequence is something like this:
> > 
> >  - common deployer identifies app and modules
> >  - (something) validates EAR
> >  - common deployer creates app MBean
> >  - for each RAR in EAR:
> >    - common deployer calls ConnectorContainer to validate a RAR, gets
> >      ObjectName for valid ones
> >    - common deployer gets connector MBean class from ConnectorContainer
> >    - common deployer creates Connector MBean w/class & ObjectName provided
> >    - common deployer sets properties on Connector MBean
> >    - common deployer tells Connector MBean to generate custom code
> >    - common deployer gets ClassSpace from Connector MBean
> >  - for each EJB JAR in EAR:
> >    - common deployer calls EJBContainer to validate a JAR, gets
> >      ObjectName for valid ones
> >    - common deployer gets EJB JAR MBean class from EJBContainer
> >    - common deployer creates EJB JAR MBean w/class & ObjectName provided
> >    - common deployer sets properties on EJB JAR MBean
> >    - common deployer tells EJB JAR MBean to generate custom code
> >    - common deployer gets ClassSpace from EJB JAR MBean
> >  - for each web app in EAR:
> >    - common deployer calls WebContainer to validate a web app, gets
> >      ObjectName for valid ones
> >    - 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
> As I mentioned above, one of the major problems with this approach
> is the tight coupling between the EARDeployer and every other deployer
> in the system. A looser coupling, whereby the EARDeployer, WARDeployer,
> RARDeployer, ServiceDeployer and XYZDeployer all re-use common Deployer
> code (maybe as a base class or maybe as a delegate), but all communicate 
> through a standard set of JSR77/JSR88 style methods (JSR77: start/stop 
> etc, JSR88: distribute, undeploy etc) mediated by the 
> DeploymentController, gives us:
>   - maximum flexibility to easily introduce support for new deployment
>     types
>   - uniformity of control flows
>   - uses existing mechanisms for co-ordinating deployment, eg checking if
>     a deployment task can proceed based on the outcome of other tasks,
>     suspending deployments for which no appropriate deployer can be
>     found, retrying failed deployments etc etc
> > Note that all the deployment plans and goals and tasks are managed by 
> > the common deployer -- when it says "creates web app MBean" and "sets 
> > properties on web app MBean" it really means "registers a task in the 
> > deployment plan to..."  So the WebContainer is doing web stuff not 
> > deployment plan stuff.
> > 
> > Then at start time, there are just a bunch of JSR-77 start() commands
> > executed, so the detailed startup logic is left to the module.
> > 
> > You seemed to be saying that there were web-specific steps that either the 
> > common deployer would do inappropriately or the web container wouldn't be 
> > given the opportunity to do -- would that still be the case?
> cheers,
> Jan

View raw message