Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to assemble multimodule maven project into one WAR?

Similar question here.

I would like to get ONE resulting WAR to be deployed from 3 different maven modules. The war modules are absolutely non-conflicting :

  • First one that has Java classes and some WEB-INF/artifacts

  • Second one are just API - interfaces - that must be either already present in container or part of the resulting war (that's what I want)

  • Third one with Implementation classes, WEB-INF/artifacts ( spring infrastructure, web.xml, etc)

First one depends on interfaces and implementation. Third one depends on the interfaces.

I have a total mess in possible options.

Do I use Overlays for this ?

Or do I use assembly plugin to be able to integrate Classes from the second one ?

Do I use Cargo plugin ?

Or is it accomplished by maven-war-plugin if I specify webResources from different module ? Because this dude is doing almost the same as I do, but with 2 war modules only, and he doesn't use assembly plugin, nor Overlays....

Please tell me, how is this done properly ?

like image 984
lisak Avatar asked Oct 25 '11 23:10

lisak


1 Answers

This just requires a little advanced use of maven jar & war plugin.

First one that has Java classes and some WEB-INF/artifacts

Let say this represents the main WAR. You just use maven-war-plugin's Overlays feature. The most basic way is specifying the war dependency :

    <dependency>
        <groupId>${groupId}</groupId>
        <artifactId>${rootArtifactId}-service-impl</artifactId>
        <version>${version}</version>
        <type>war</type>
        <scope>runtime</scope>
    </dependency>

and tell maven war plugin to merge assets of this dependency into the main war (where we are now)

<plugin>
    <artifactId>maven-war-plugin</artifactId>
    <configuration>
        <dependentWarExcludes>WEB-INF/web.xml,**/**.class</dependentWarExcludes>
        <webResources>
            <resource>
                <!--  change if necessary -->
                <directory>src/main/webapp/WEB-INF</directory>
                <filtering>true</filtering>
                <targetPath>WEB-INF</targetPath>
            </resource>
        </webResources>
    </configuration>
</plugin>

You also include a jar type dependency on the second one (it will be a JAR in WEB-INF/lib/)

    <dependency>
        <groupId>${groupId}</groupId>
        <artifactId>${rootArtifactId}-service</artifactId>
        <version>${version}</version>
        <type>jar</type>
    </dependency>

And you also need to specify dependency on the classes from the third WAR :

    <dependency>
        <groupId>${groupId}</groupId>
        <artifactId>${rootArtifactId}-service-impl</artifactId>
        <version>${version}</version>
        <classifier>classes</classifier>
        <type>jar</type>
    </dependency>

Notice of the classifier, it is necessary because you are specifying 2 dependencies of the same artifact... To make it work, you have to set up jar plugin in the third artifact (war type artifact), regarding the classifier and the fact that you need 2 packages from one artifacts (war & jar):

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <!-- jar goal must be attached to package phase because this artifact is WAR and we need additional package -->
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>jar</goal>
            </goals>
            <configuration>
            <!-- 
                classifier must be specified because we specify 2 artifactId dependencies in Portlet module, they differ in type jar/war, but maven requires classifier in this case
            -->
                <classifier>classes</classifier>
                <includes>
                    <include>**/**.class</include>
                </includes>
            </configuration>
        </execution>
    </executions>
</plugin>
like image 161
lisak Avatar answered Oct 08 '22 14:10

lisak