This is how Maven snapshot version works!

Time:2020-6-28

The mystery of bug’s life

Today I share another story about problem solving. Please see the error in the box below. Obviously, we can’t find this class!

This is how Maven snapshot version works!

Let’s check the problem according to the idea of normal people. Since we can’t find the class, let’s see if there is a dependent jar package first. If there is no such case, it’s overwhelming evidence.

But it didn’t work out. There was a package in the compiled lib directoryorder-api-2.0-SNAPSHOT.jar

I still don’t believe it, so I put order-api-2.0- SNAPSHOT.jar Unzip, see if there is any class we need in it. Really, I feel heavy here.

Ordinary people will be confused when they arrive here, but I’m still young and have enough brains. Next, let’s see if there is any problem with classpath configuration. If order-api-2.0- SNAPSHOT.jar If it’s not in the classpath, then naturally it’s impossible to find the class, witty me.

So I looked at meta-inf/ MANIFEST.MF File, found that it depends onorder-api-2.0-20200225.024541-15.jar,What’s the situation? It’s time stamped.

Finally, the truth is revealed. What the classpath points to isorder-api-2.0-20200225.024541-15.jar,But only in Liborder-api-2.0-SNAPSHOT.jar。So it’s not wrong not to find class.

Packaging configuration information

When Maven deploy, it will automatically time stamp the snapshot version, as shown in the following figure:

This is how Maven snapshot version works!

The following is the packaging configuration of the current project:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <version>2.3.1</version>
  <configuration>
    <archive>
      <manifest>
        <mainClass>com.xxx.web.WebApp</mainClass>
        <addClasspath>true</addClasspath>
        <classpathPrefix>lib/</classpathPrefix>
      </manifest>
    </archive>
  </configuration>
</plugin>
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
</plugin>

The assembly plug-in is used, and the corresponding configuration is as follows:

assembly.xml

<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>bin</id>
<formats>
    <format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
    <dependencySet>
        <outputDirectory>/</outputDirectory>
        <unpack>false</unpack>
        <includes>
            <include>${artifact}</include>
        </includes>
        <outputFileNameMapping>xxx-web.jar</outputFileNameMapping>
    </dependencySet>
    <dependencySet>
        <outputDirectory>/lib</outputDirectory>
        <useProjectArtifact>false</useProjectArtifact>
        <unpack>false</unpack>
    </dependencySet>
</dependencySets>
</assembly>

After packaging, there will be a jar package and a lib directory in the directory, as follows:

-xxx-web.jar
-lib
  -xxx.jar
  -yyy.jar

Solution

The problem to be solved now is that the snapshot dependency in classpath is inconsistent with the actual jar package in the Lib directory.

It is mainly two plug-ins, so there will be inconsistencies.

You can add < useuniqueversions > false < / useuniqueversions > to the Maven jar plugin plug-in to force packaging MANIFEST.MF Jar timestamp version that the file does not record.

The Maven assembly plugin plug-in needs to be assembly.xml In the dependency set, add outputfilenamemapping=${ artifact.artifactId }-${ artifact.baseVersion }.${ artifact.extension }

To fix the name so that you can remove the timestamp.

The following is the complete configuration after modification:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <version>2.3.1</version>
  <configuration>
    <archive>
      <manifest>
        <mainClass>com.xxx.web.WebApp</mainClass>
        <addClasspath>true</addClasspath>
        <classpathPrefix>lib/</classpathPrefix>
        <useUniqueVersions>false</useUniqueVersions>
      </manifest>
    </archive>
  </configuration>
</plugin>
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
</plugin>

assembly.xml

<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>bin</id>
<formats>
    <format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
    <dependencySet>
        <outputDirectory>/</outputDirectory>
        <unpack>false</unpack>
        <includes>
            <include>${artifact}</include>
        </includes>
        <outputFileNameMapping>xxx-web.jar</outputFileNameMapping>
    </dependencySet>
    <dependencySet>
        <outputFileNameMapping>
  ${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension}  
        </outputFileNameMapping>
        <outputDirectory>/lib</outputDirectory>
        <useProjectArtifact>false</useProjectArtifact>
        <unpack>false</unpack>
    </dependencySet>
</dependencySets>
</assembly>

Although it has been solved, it still feels troublesome. The spring boot Maven plugin plug-in is still easy to use. At least there is no such time stamp problem. For the new project, we suggest that you pack it with the spring boot Maven plugin plug-in.

About the authorYin Ji Huan, a simple technical enthusiast, “Spring Cloud micro Service – full stack technology and case analysis”, “Spring Cloud micro service portal combat and advanced” author, official accountApe worldSponsor.