On Thu, 2003-07-03 at 17:06, Vincent Massol wrote:
> Maven plugins need to be environment-aware!
> 
> Let's imagine you wish to use Maven for J2EE development (quite a common
> scenario). As you progress towards production you will notice that you
> Maven projects will need to be environment-aware. 

I would agree that your projects may need to be environment aware but I
don't think it follows that plugins need to be environment aware.

> Indeed, your artifacts
> will not be the same whether you deploy them in the development
> environment, the integration environment or in the production
> environment. 

That is true, to use my own example I do this with the Plexus plugin
where I generate several containers dependending on my testing or
deployment situation. The entire Plexus plugin is a tag lib that works
internally only with the parameters you hand it. I think what you want
to do is parameterize the Plugins, yes?

> Let's take two example. A development environment may use
> JBoss as its container whereas you wish to use WebSphere/WebLogic (pick
> your preferred container) in production (Not that this is a good
> strategy but it happens all the time). That requires to include a
> jboss.xml file in META-INF/ for your EJB-JAR for JBoss and another one
> for the other container. Even better, the jboss.xml will not be the same
> for the different environment; the one for production might use a
> cluster configuration whereas the one for development will usually not,
> etc. The same applies for a lot of other artifacts: WAR, EAR, RAR,
> configuration files for containers, start/stop scripts, etc.

So, yes, I think what you really want to do is parameterize the plugins.
Based on a set of criteria you decided what artifacts you want deployed.
That's perfectly reasonable.

> More generally, there is a need to know what is the environment used
> when building a project. The environment could also be things such as
> the version of the JDK the project is built with, the OS (although this
> doesn't affect much the java sources) or any other parameter related to
> the building or target environment.
> 
> How do you deal with this in Maven?

I think most effectively the plugin has to written well enough so that
it can deal with the variability. To use the Plexus plugin as an example
again, I determine what is required before the plugin is run, select my
parameters based on whatever criteria and then pass that information on
to the plugin as a set of parameters.

> One important thing to understand is that artifacts generated for a
> given environment cannot be mixed with the artifacts generated for
> another environment. There are 2 solutions to deal with this: one
> involves 
> adding the environment characteristic/name in the artifact name, such as
> acme-registration-production-1.0.jar and
> acme-registration-development-1.0.jar. Another solution is to have
> separate Maven remote repositories 
> (one per environment). The way to deal with this is easy: Have the
> following in your build.properties/project.properties:
>
> env.name=development
> maven.repo.remote=http://ip:port/maven/repository/${env.name}
> 
> Then comes the more difficult question of how to make the project build
> environment-aware. With the current Maven, the following solution works
> (but is tiresome). First, start by creating environment-aware project
> directory structures. For example, for an EJB-JAR project, you would
> have something like:
> 
> myproject
>   |_ src
>     |_ ejb
>       |_ development
>         |_ META-INF
>           |_ jboss.xml
>       |_ integration
>         |_ META-INF
>           |_ jboss.xml
>       |_ production
>         |_ META-INF
>           |_ jboss.xml
>       |_ share
>         |_ META-INF
>           |_ ejb-jar.xml
>   |_ [rest of the project]
>   
> Now, how do we deal with this? The current solution is to read the
> plugin source code and find a way to intercept it before it includes the
> META-INF files in the EJB-JAR. A post goal of ejb:init looks good. So
> you need to write a maven.xml and write something like:
> 
> <postGoal name="ejb:init">
>   <copy todir="${maven.build.dir}/src/ejb" overwrite="true"
> filtering="on">
>     <fileset dir="src/ejb/share"/>
>   </copy>
>   <copy todir="${maven.build.dir}/src/ejb" overwrite="true"
> filtering="on">
>     <fileset dir="src/ejb/${env.name}"/>
>   </copy>
> </postGoal>

I believe if this type of behaviour is necessary then the plugin is
written incorrectly. Anything in the plugin where a selection is
required should be made a parameter.

> And then write the following in the project.properties:
> 
> maven.ejb.src = ${maven.build.dir}/src/ejb
> 
> You would also add a env.name property in your build.properties (or on
> the command line when you start maven)
> 
> env.name = development (for example)
> 
> Of course, you would have to do this for all your projects and for all
> types of environment-aware projects. That's very tiresome. You could of
> course improve that a little by creating a jelly
> <copy-environment-resources> tag and using that in the maven.xml but
> that wouldn't help much.
> 
> The real problem is that the current Maven plugins are not
> environment-aware...

I really don't think so. I believe that the problem is that the plugins
are not written correctly. I think trying to mix in environment
information into the plugins is not really a good idea. I think it will
make the plugins more complicated and really does not separate concerns
very well.

I am not wholly familiar with all the plugins that you speak of but I'm
doing something very similiar to what you are with Plexus with the
plugin being fully parameterized.

I will use the thought experiment of writing a plugin purely in Java. If
we did say write a plugin in Java how would you make the environment
information available? You would probably make the environment
information available from the parameters you could set for the plugin.
Now you could always use a Map as one of the parameters so you could
plan for expansion. But I think the real issue is that Jelly doesn't
really promote any rigorous separation and a lot of plugin rely on
information that happens to be in the context when it really should take
the information from a parameter.

> The solution is of course to make them environment-aware by building
> this logic in them. For example, Maven could have the following
> mechanism:
> 
> * An environment plugin which would contain the
> <copy-environment-resources src="" dest=""/> tag. That plugin would also
> define a variable called maven.environment.name which would default to
> "" (empty string). In our example, we would override it to
> "development", "integration", "production", "jdk12", "jdk13", "j2ee1.2",
> "j2ee1.3", etc. This jelly tag would also standardize on a shared
> environment config directory name. For example, by having a property:
> maven.environment.share.dir=share. The tag logic would be the same as
> shown above in our postGoal.

Again, I really don't think this is necessary and is something that
should be parameterized. I think this would also let a plugin focus on a
small, simple, coherent task. This does put the onus to select the
parameters for a plugin but how these are chosen will vary on the
situation. Let the plugin be simple and build any custom selection
mechanism on top, this selection would build a set of parameters that
are passed into the plugin.

> * Modify the existing plugins that should be environment aware so that
> they become environment-aware. They would thus use the
> <copy-environment-resources/> tag and copy/filter the config files in
> the target directory and use that as the source of the config. In order
> to boost performance a little, they could test if the
> maven.environment.name property is an empty string or not, and if so,
> bypass the copy step.

I'm not really in favour of this modification but I am in favour of
making all the plugins straight tab libs. I think this would make the
plugins cleaner and allow for what you require.

> * Almost any plugin that uses config files would need to be environment
> aware. The java plugin would need that. Same for the test plugin, etc.
>   
> What do you think?

I'm more in favour of cleaning up the plugins by taking an individual
plugin and turning it completely into a tag lib. In the case of plugins
that provide some convenience by taking values from the context a small
goal could be made to take these values and pass them into a cleaned up
plugin that takes parameters.

If all our plugins were written in this manner they would become
generally useful Jelly tag libs that were not maven specific. Any Maven
specific information could be selected and passed in as parameters. This
way we have a set of simple tag libs and users are free to build any
selection mechanism required to choose parameters for plugin execution.
We could certainly provide some convenience goals to select some
defaults which would effectively be the same as what we're doing now by
mixing the context information in with the plugin code.

> Thanks
> -Vincent
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
-- 
jvz.

Jason van Zyl
[EMAIL PROTECTED]
http://tambora.zenplex.org

In short, man creates for himself a new religion of a rational
and technical order to justify his work and to be justified in it.
  
  -- Jacques Ellul, The Technological Society


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to