PluginPOMGuidance

Guidance for building POMs


It is expected that this will end up in the Plugin documentation – for now this is just for discussion

When building the POM for a plugin there are multiple goals.

  1. We want the POM to represent dependency on a consistent state of an IdP (this would usually be the minimum IdP version the plugin supports).
  2. We want to avoid any dependency leakage from the IdP into the plugin (and any projects deriving from the IdP).
  3. We want to avoid the project or plugin developer from accidentally shipping jars in the plugin which are subject to restrictive licenses that do not allow us to ship them. Such Jars need to be downloaded by the deployer and there is an infrastructure that deploys this.

We, therefore, have come up with the following guidance:

  • The plugin pom SHOULD NOT have the idp-parent project as its parent (or an ancestor). It MAY, if produced by the Shibboleth Project, use the java-parent-project POM as its parent, generally the version corresponding to the minimum IdP version supported.
    • While this leads to some duplication, relying on idp-parent directly causes dependency contamination and causes unrelated settings connected to site generation to leak into plugins.
  • All dependencies of the plugin MUST be explicitly mentioned in the plugin project’s pom (this is just hygiene).
    • All IdP-supplied dependencies MUST have scope ‘provided’ (or 'test'). This avoids jar pollution downstream from the plugin (or technically from where they are 'provided'). Note that ‘provided’ implies ‘test’ so plugins can be tested outside an IdP and the dependencies will turn up.
    • All dependencies which cannot be shipped (e.g. due to restrictive licensing as mentioned) MUST have scope ‘provided’; this avoids accidentally shipping the dependency in the final package.
    • Depending on the kitting mechanism used, newly required and shippable dependencies MAY have scope ‘compile’. But note that we do not have the capability of preventing plugin dependencies from conflicting. If this is a concern, shadowing is the only real answer (see below).
  • IdP and OpenSAML dependencies SHOULD be limited to ‘api’. This allows a wide range of IdP versions to be supported (usually, but not always up to but not including the next major version) . Non-API dependencies by their nature imply that exactly one version of the IdP is supported without explicit testing.
    • That said, test dependencies of 'impl' plugin modules MAY depend on IdP 'impl' dependencies to facilitate unit or integration tests.
      • It is unlikely that 'api' plugin modules will require IdP 'impl' test dependencies. If they do, either the IdP 'impl' dependency needs to be exposed as part of the API, or the plugin's API needs refactoring.
  • Plugins MAY consider using shadowing during assembly to embed specific dependency versions, though the IdP itself will (almost certainly) never do so.

Project Naming

Just sketching out and recording some plausible naming conventions for the project's own plugins...

The examples are based on a plugin providing a "feature".

Git Repo: java-idp-plugin-feature

Parent POM coordinates:

    <name>Shibboleth IdP :: Plugins :: Feature</name>
    <groupId>net.shibboleth.idp.plugin</groupId>
    <artifactId>idp-plugin-feature</artifactId>

Typical submodules:

    <modules>
        <module>feature-api</module> <!-- perhaps, many plugins won't have an API -->
        <module>feature-impl</module>
        <module>feature-dist</module>
    </modules>

Implementation POM:

    <name>Shibboleth IdP :: Plugins :: Feature Impl</name>
    <artifactId>idp-plugin-feature-impl</artifactId>

    <properties>
        <automatic.module.name>net.shibboleth.idp.plugin.feature.impl</automatic.module.name>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.target.directory}</outputDirectory>
                            <includeScope>runtime</includeScope>
                            <excludeTransitive>true</excludeTransitive>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId> 
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifestEntries>
                            <Automatic-Module-Name>${automatic.module.name}</Automatic-Module-Name>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>

Distribution POM:

    <name>Shibboleth IdP :: Plugins :: Feature Distribution</name>
    <artifactId>idp-plugin-feature-dist</artifactId>
    <packaging>pom</packaging>

    <properties>
        <dist.finalName>shibboleth-idp-plugin-feature-${project.version}</dist.finalName>
    </properties>