12

Suppose I have a module A:jar, whose runtime and compilation set of dependencies depends on the JDK version. In my example, I have a pre-jdk6-profile for JAXB API: prior to JDK 1.6.0 I need to include jaxb-api-nnn.jar as a compile dependency. This profile is placed to A.pom.

I also have module B:war, which depends on A:jar. I want to be able to activate this profile on a build server to build the JDK 1.5.x deliverable. When I execute Maven with a given profile activated, I get the message:

mvn -Ppre-jdk6-profile -o install
[WARNING]
        Profile with id: 'pre-jdk6-profile' has not been activated.

and jaxb-api-nnn.jar is missing in resulting B.war. However if I activate this profile when building from the parent pom.xml, everything is OK. That means the profiles are not inherited from dependencies, and the parent multi-module pom.xml was able to build everything correctly because it seems like all profiles are merged in reactor.

Shifting the profile to parent pom makes things worse, as the dependencies are applied to all other projects (e.g. to C:ear). Are there nice solutions for this task, namely, if any module A depends on module B, then all compile and runtime dependencies which are activated by a profile, are correctly handled?

The profile in project A:jar follows:

<project ...>
    <artifactId>A</artifactId>
    <packaging>jar</packaging>
    ...
    <parent>
        <artifactId>P</artifactId>
        ...
    </parent>

    <profiles>
        <profile>
            <id>pre-jdk6-profile</id>

            <activation>
                <jdk>(,1.6.0)</jdk>
            </activation>

            <dependencies>
                <dependency>
                    <groupId>javax.xml.ws</groupId>
                    <artifactId>jaxws-api</artifactId>
                </dependency>
            </dependencies>
        </profile>
    </profiles>
...
</project>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
dma_k
  • 10,431
  • 16
  • 76
  • 128

2 Answers2

17

a) In a multi-module build, you should always build from the top pom, never from an individual module. If you want to build only one module, use advanced reactor options (see mvn --help) like this:

mvn -pl mymodule

b) Define and activate the profile in the parent pom, but add the configuration in the child pom.

parent pom.xml

<profiles>
    <profile>
         <id>pre-jdk-6</id>
         <activation>
            <jdk>(,1.6.0)</jdk>
         </activation>
    </profile>
</profiles>

child pom.xml

<profiles>
    <profile>
        <id>pre-jdk-6</id>

        <dependencies>
            <dependency>
                <groupId>javax.xml.ws</groupId>
                <artifactId>jaxws-api</artifactId>
            </dependency>
        </dependencies>
    </profile>
</profiles>
Lee Meador
  • 12,829
  • 2
  • 36
  • 42
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • Do I need to add the 2nd part to module `A` or to module `B`? – dma_k Aug 22 '10 at 20:44
  • 1
    both. In the JAR with `provided`, in the webapp with default scope. But in both inside the profile. – Sean Patrick Floyd Aug 23 '10 at 04:43
  • I believe, I can use only (b) if I run builds on Hudson. Thanks for you hints. – dma_k Sep 07 '10 at 13:37
  • I don't get it, what's the activation of child profile? Is parent profile an empty profile? How are the two profiles linked together? – djjeck Mar 14 '14 at 02:33
  • 1
    I suspect that the child profile should be pre-jdk-6 as well? – Eric B. May 11 '16 at 17:25
  • @djjeck: The provided solution shows that activation and actual profile action (in my case adding some dependency) should be separated. Activation should go to parent pom (which is shared between modules `A` and `B` in my case). Profiles are linked by ID and are actually "merged" from top to bottom. – dma_k Mar 08 '17 at 12:22
6

Several notes way after the fact:

  1. When you use -P profName, it activates a profile named 'profName'
  2. After that, it disables all profiles that have an <activation> tag for them. It doesn't matter whether they are activated by the java version, as in the example, or by default or env value or anything.
  3. That means the -P causes any otherwise activated profile to become deactivated.

Solution: Either use <activation><jdk>...</jdk></activation> or use -P but do not use both.

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
Lee Meador
  • 12,829
  • 2
  • 36
  • 42
  • 2
    Despite this rule holds true in most circumstances, there seem to be certain exceptions - at least in my experience with Maven 3.3+. Suppose there is a Maven descriptor (`pom.xml`) that activates a profile based on Java version. Even if we explicitly choose a profile with `-P profName`, the Java-specific profile will still be activated! The same goes for other "profiles automatically triggered based on the detected state of the build environment" as Maven documentation kindly explains. – leonidos79 Apr 24 '19 at 08:36