Friday, June 1, 2018

Maven dependencies basics

Source: https://maven.apache.org/pom.html

Always required in a POM:
  • groupId
  • artifactId
  • version
Dependency hierarchy:
  • All POMs inherit from Maven's Super POM.
    This is why some properties you specify but not use have effect. For example you can set the compiler version with these properties:
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  • To set up a POM hierarchy within your project, all POMs that are specified as <parent> in other POMs or that have <modules> (aggregation aka. multi-module projects) must use <packaging>pom</packaging>.
  • Note:  A POM project may be inherited from - but does not necessarily have any modules that it aggregates. Conversely, a POM project may aggregate projects that do not inherit from it.
Dependency scope:
  • compile - this is the default scope, used if none is specified. Compile dependencies are available in all classpaths. Furthermore, those dependencies are propagated to dependent projects.
  • provided - this is much like compile, but indicates you expect the JDK or a container to provide it at runtime. It is only available on the compilation and test classpath, and is not transitive.
  • runtime - this scope indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath.
  • test - this scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases. It is not transitive.
  • system - this scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository.
Exclusion of transitive dependencies:
  • One by one: specify them one by one
  • All: use the * wildcard for both the groupId and artifactId

Show README and CHANGELOG on Maven Site

It is common that the project's README contains valuable information about the project. For example on a repository's webpage in Gitlab or Github, the README is displayed by default.
Here's a way to publish the README and CHANGELOG markdown files on the project's Maven Site:

In the Site descriptor (/src/site/site.xml) reference the files you want to publish:
<?xml version="1.0" encoding="UTF-8"?>
<project>
  <body>
    <menu name="Documentation">
      <item name="README" href="docs/README.html"/>
      <item name="CHANGELOG" href="docs/CHANGELOG.html" />
    </menu>
  </body>
</project>

In the pre-site build phase copy the files to the markdown resource directory. The site plugin transforms the documentation to HTML and outputs it to the corresponding target directory.
After the site building finished, clean up the duplicate files:
<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <configuration>
          <encoding>${project.build.sourceEncoding}</encoding>
        </configuration>
        <executions>
          <execution>
            <!-- Copy the readme and such files to the site source files so that a page is generated from it. -->
            <id>copy-docs</id>
            <phase>pre-site</phase>
            <goals>
              <goal>copy-resources</goal>
            </goals>
            <configuration>
              <outputDirectory>${basedir}/src/site/markdown/docs</outputDirectory>
              <resources>
                <resource>
                  <directory>${basedir}</directory>
                  <includes>
                    <include>README.md</include>
                    <include>CHANGELOG.md</include>
                  </includes>
                </resource>
              </resources>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-clean-plugin</artifactId>
        <!-- Delete the markdown/docs directory to remove the readme and such duplicate files from the site source files. -->
        <executions>
          <execution>
            <id>clear-docs</id>
            <phase>site</phase>
            <goals>
              <goal>clean</goal>
            </goals>
            <configuration>
              <filesets>
                <fileset>
                  <directory>src/site/markdown/docs</directory>
                  <followSymlinks>false</followSymlinks>
                </fileset>
              </filesets>
              <excludeDefaultDirectories>true</excludeDefaultDirectories>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

To show the process in terms of file structure:
The normal state:
.
+-- src 
| +-- site
| | +-- site.xml
After the files were copied:
.
+-- src 
| +-- site
| | +-- markdown
| | | +-- docs
| | | | +-- README.md
| | | | +-- CHANGELOG.md
| | +-- site.xml
The output in site target:
.
+-- docs
| +-- README.html
| +-- CHANGELOG.html
+-- index.html

A bonus note regarding the deployment url: it can be changed it the distributionManagement section:
<project>
  ...
  <distributionManagement>
    <site>
      <url>${maven.reports.deployBase}/${project.groupId}</url>
    </site>
  </distributionManagement>
  ...
</project>