Paul Lowry created MNG-5408:
-------------------------------

             Summary: Explicit profile activation in pom.xml
                 Key: MNG-5408
                 URL: https://jira.codehaus.org/browse/MNG-5408
             Project: Maven 2 & 3
          Issue Type: Improvement
          Components: Profiles
    Affects Versions: 3.0.4
            Reporter: Paul Lowry


+Background:+

Organisations should be able to define complex maven tasks, each involving 
multiple plugin executions, in a way that is standardised for use in all 
projects.

The obvious solution would seem to be profiles:
* They allow us to define maven project configuration and multiple plugin 
executions
* They can be enabled/disabled, and they are not mutually exclusive, so we can 
use them to run execution A or execution B of the same plugin, or A and then B, 
or any other sequence (note: this sort of control is not available in 
pluginManagement)

For example, consider an organisation where some project teams do integration 
testing of war artifacts by running them in Jetty, whereas others use Tomcat. 
Both scenarios require several plugins to run, and though the process is 
similar it is not the same (for our example, let's assume that Jetty requires a 
test context file, and Tomcat projects have a different naming scheme for their 
test classes).

Using profiles in a root pom, which is the parent for all projects in the 
organisation, we can make the process for running a war in Jetty/Tomcat quite 
simple, and more importantly quite consistent:

{code:xml|title=root.pom.xml}
<project>
    <profiles>
        <!--
        profile for running integration tests using jetty
        -->
        <profile>
            <id>runJetty</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-resources-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>runJetty.prep</id>
                                <phase>pre-integration-test</phase>
                                <goals>
                                    <goal>copy-resources</goal>
                                </goals>
                                <configuration>
                                    <resources>
                                        <resource>
                                            
<directory>\${project.build.testOutputDirectory}/jetty</directory>
                                            <filtering>true</filtering>
                                        </resource>
                                    </resources>
                                    
<outputDirectory>\${project.build.directory}/\${project.build.finalName}</outputDirectory>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>org.mortbay.jetty</groupId>
                        <artifactId>jetty-maven-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>runJetty.start</id>
                                <phase>pre-integration-test</phase>
                                <!-- start server in jetty, using property 
${runJetty.port} -->
                            </execution>
                            <execution>
                                <id>runJetty.stop</id>
                                <phase>post-integration-test</phase>
                                <!-- stop jetty -->
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-failsafe-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>runJetty.test</id>
                                <phase>integration-test</phase>
                                <goals>
                                    <goal>integration-test</goal>
                                    <goal>verify</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
        <!--
        profile for running integration tests using tomcat
        -->
        <profile>
            <id>runTomcat</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.tomcat.maven</groupId>
                        <artifactId>tomcat6-maven-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>runTomcat.start</id>
                                <phase>pre-integration-test</phase>
                                <!-- start server in tomcat, using property 
${runTomcat.port} -->
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-failsafe-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>runTomcat.test</id>
                                <phase>integration-test</phase>
                                <goals>
                                    <goal>integration-test</goal>
                                    <goal>verify</goal>
                                </goals>
                                <configuration>
                                    <includes>
                                        
<include>\${runTomcat.testPattern}</include>
                                    </includes>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
</project>
{code}

A war project, with the above as its parent, can be configured to start its 
build artifact and run all integration tests, using Jetty or Tomcat as follows:

{noformat:title=project tested using Jetty}
<project>
    <properties>
        <runJetty.port>7070</runJetty.port>
    </properties>
</project>
{noformat}

{noformat:title=the same project tested using Tomcat}
<project>
    <properties>
        <runTomcat.port>7070</runTomcat.port>
        <runTomcat.testPattern>**/*AcceptanceTest.java</runTomcat.testPattern>
    </properties>
</project>
{noformat}

Having defined these re-usable profiles, we then reach the question of how to 
activate them automatically in the organisation's various war projects (since 
the organisation's best practices demand that every build of a war project 
should run integration tests).

Profiles can be activated by JDK version or OS, but these are not specific 
enough conditions. They can also be activated by command line properties, but 
these are too explicit - in this case we want our profile to run automatically. 
The only other activation condition is for a file to exist; but we cannot look 
in the target directory because profile activation is evaluated before the 
build starts; nor can we reliably depend on 'src/main/webapp', since different 
projects may arrange their sources differently, and some projects might want to 
disable the profile.

+Problem:+

So we hit a problem, namely: A project should be able to activate a profile 
explicitly; but the activation mechanisms provided out of the box are not 
refined enough.

Several alternative ways have been suggested to activate profiles, such as 
packaging type (http://jira.codehaus.org/browse/MNG-4154), artifactId/groupId 
(http://jira.codehaus.org/browse/MNG-944), and pom properties. This last is 
probably the most widely mentioned, and was even used as the example for a 
custom profile activator feature, that was spiked in Maven 2.1 but never made 
it into the product. See these links for details...
* 
http://maven.40175.n5.nabble.com/Activating-a-profile-in-settings-xml-based-on-a-property-set-in-pom-xml-tp512562p512598.html
* 
http://maven.40175.n5.nabble.com/profile-activation-based-on-property-properties-in-POM-tp88010p88011.html
* http://docs.codehaus.org/display/MAVEN/Custom+Profile+Activators

If pom properties could activate profiles, it would certainly work nicely for 
the example above, in that developers could enable Jetty or Tomcat as follows:

{code:xml|title=root.pom.xml}
<project>
    <profiles>
        <profile>
            <id>runJetty</id>
            <activation>
                <property>
                    <name>runJetty</name>
                    <value>true</value>
                </property>
            </activation>
            ...
        </profile>
        <profile>
            <id>runTomcat</id>
            <activation>
                <property>
                    <name>runTomcat</name>
                    <value>true</value>
                </property>
            </activation>
            ...
        </profile>
    </profiles>
</project>
{code}

{noformat:title=project tested using Jetty}
<project>
    <properties>
        <runJetty>true</runJetty>
        <runJetty.port>7070</runJetty.port>
    </properties>
</project>
{noformat}

{noformat:title=the same project tested using Tomcat}
<project>
    <properties>
        <runTomcat>true</runTomcat>
        <runTomcat.port>7070</runTomcat.port>
        <runTomcat.testPattern>**/*AcceptanceTest.java</runTomcat.testPattern>
    </properties>
</project>
{noformat}

However, none of these improvements (or similar) have ever been released.

It seems to me like I'm missing something. Maybe the Maven 
developers/committers consider profiles an inappropriate way to configure 
builds like the example above; or maybe it's just too costly to activate 
profiles using info from the pom model.

+Summary:+

I'd like very much to understand why profiles cannot (or should not) be used in 
scenarios like the one described above.

I'd also like to know if John Casey's custom profile activator might ever see 
the light of day, or if there is some alternative solution on the roadmap for 
Maven.

Thanks & Regards

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: 
https://jira.codehaus.org/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Reply via email to