开发者

Maven assembly plugin produces undeployable war file

I'm working on a multi module project using Spring, Hibernate, GWT and Maven 3 and try to deploy a war-file distribution to a servlet container (preferably Tomcat 7 or Jetty 8). I create the war-file using maven-assembly-plugin 2.2.1 (I'm running maven 3). During the maven build everything works perfectly and the distribution archive is created.

But when I try to deploy the war file, I get ClassNotFound-Exceptions (e.g. Spring ContextLoaderListener and the like) although everything is in place (Web-inf/lib etc. pp.). So, the webapp isn't starting. Then I unpack the war-file into the servlet containers webapp directory and everything is working fine... ??

After further investigation I came across the following thing: If I take an arbitrary war file A' created by maven-war-plugin (!), replace its content with the unpacked content from the war file I created using maven-assembly-plugin (let me call it A.) I can see two things happen:

  1. the resulting war file A' is a few bytes smaller than my original file A although their content is identical

  2. the deployment of A' suddenly works like a charm

This is weird and I have absolutely no idea what's happening. Maybe there is an issue and maven-war-plugin and maven-assembly-plugin handle war file packaging differently?! I mean, a war is only a renamed zip file with some predefined structure... Maybe it has absolutely nothing to do with maven but with file encoding or other things? Any ideas on this? I appreciate any hint, that could help me in investigating this...

This is my assembly descriptor

<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>dist</id>
<formats>
    <format>war</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>

<dependencySets>
    <dependencySet>
        <unpack>true</unpack>
        <includes>
            <include>mypackage.client:parametermgmt:*</include>
            <include>mypackage.static:client:*</include>
        </includes>
        <useProjectArtifact>false</useProjectArtifact> 
        <outputDirectory>/</outputDirectory> 
    </dependencySet>

    <dependencySet>
        <unpack>false</unpack>
        <includes>
            <include>mypackage.server.database:domain:*</include>
            <include>mypackage.server.businessobjects:BOdomain:*</include>
            <include>mypackage.server.security:security:*</include>
            <include>mypackage.server.services:paramgmt:*</include>
        </includes>
        <useProjectArtifact>false</useProjectArtifact>    
        <outputDirectory>Web-inf/lib</outputDirec开发者_如何学JAVAtory>   
    </dependencySet>

    <dependencySet>
        <unpack>true</unpack>
        <includes>
            <include>mypackage.static:server:*</include>
        </includes>
        <useProjectArtifact>false</useProjectArtifact> 
        <outputDirectory>/</outputDirectory> 
    </dependencySet>

    <dependencySet>
        <unpack>false</unpack>
        <includes>
            <include>*</include>
        </includes>
        <excludes>
            <exclude>mypackage.*</exclude>
        </excludes>
        <scope>runtime</scope>
        <useProjectArtifact>false</useProjectArtifact>
        <outputDirectory>Web-inf/lib</outputDirectory>
    </dependencySet>

</dependencySets>


The maven-assembly-plugin is not intended to create a war. For this purpose use the maven-war-plugin instead.

If you need to create war files for different environments like test,qa, production. This can be used as well a base for different app servers. But if we are talking about a application server this means we should create ear files instead of war files (This means to use maven-ear-plugin instead of maven-war-plugin).

|-- pom.xml
`-- src
    |-- main
    |   |-- java
    |   |-- resources
    |   |-- environment
    |   |   |-- test
    |   |   |   `-- database.properties
    |   |   |-- qa
    |   |   |   `-- database.properties
    |   |   `-- production
    |   |       `-- database.properties
    |   `-- webapp

You need the following assembly for that (for every environment) which can be created based on this as a template:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">

  <id>test</id>
  <formats>
    <format>war</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <dependencySets>
    <dependencySet>
      <unpack>true</unpack>
      <useProjectArtifact>true</useProjectArtifact>
    </dependencySet>
  </dependencySets>
  <fileSets>
    <fileSet>
      <outputDirectory>WEB-INF</outputDirectory>
      <directory>${basedir}/src/main/environment/test/</directory>
      <includes>
        <include>**</include>
      </includes>
    </fileSet>
  </fileSets>
</assembly>

To support different artifacts for different environments this is the time for the maven-assembly-plugin like this:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <executions>
          <execution>
            <id>test</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
            <configuration>
              <descriptors>
                <descriptor>${project.basedir}/src/main/assembly/test.xml</descriptor>
              </descriptors>
            </configuration>
          </execution>
          <execution>
            <id>qa</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
            <configuration>
              <descriptors>
                <descriptor>${project.basedir}/src/main/assembly/qa.xml</descriptor>
              </descriptors>
            </configuration>
          </execution>
          <execution>
            <id>production</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
            <configuration>
              <descriptors>
                <descriptor>${project.basedir}/src/main/assembly/production.xml</descriptor>
              </descriptors>
            </configuration>
          </execution>
        </executions>
      </plugin>

The result is creating three different war files which can be distinguished by their appropriate classifier with a single call (detailed description can be read here):

mvn clean package
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜