Code Monkey home page Code Monkey logo

module-info-maven-plugin's Introduction

module-info

A utility for generating module-info.class files from any JDK version (including 8). The module-info.class file is generated by reading a source YAML file, optionally merging in values from your project and/or build system, and then producing the class file from the result.

YAML file format

Module information is given in the YAML file format.

Root elements

The YAML descriptor can contain the following basic elements:

Table 1. Root elements
Name Description

name

The name of the module as a string (required)

version

The module’s version as a string (optional, may be provided by build system)

open

A boolean value; set to true to open the entire module (optional)

mainClass

The name of the module’s main class as a string, if it is runnable (optional)

packages

A list of package names to include in the module definition (optional, may be detected)

requires

A list of dependency modules that are used by this module (optional, may be provided by build system)

exports

A list of exported packages that are provided by this module (optional, may be detected)

opens

A list of exported packages that are provided by this module with reflection access (optional)

uses

A list of service class names (as strings) that are used by this module (optional, may be detected)

provides

A list of provided services that are provided by this modules for other modules to use (optional, may be detected)

The following elements may also be given but are only useful for advanced use cases:

Table 2. Less common root elements
Name Description

synthetic

A boolean value; set to true to set the ACC_SYNTHETIC flag on the module (optional)

mandated

A boolean value; set to true to set the ACC_MANDATED flag on the module (optional)

sourceFile

The string name of the source file of this descriptor (optional)

annotations

A list of Annotations that are attached to the module declaration (optional)

Version strings

Version strings do not have any particular syntax requirement. Normally the version string will be extracted by your build system and added to the module descriptor automatically, so it is likely that in this case, the version string for your project will adhere to the syntax requirements of the build system.

The Java platform module system does care about version syntax in certain cases. The module system contains an API which represents the module descriptor. Version strings which fail to follow the rules set by the descriptor will fail to parse by this API. However, few (if any) programs rely on this API, so for most programs, this is not anything to be concerned about.

Module requirements (dependencies)

Required modules are described as a list of nested objects which can contain the following elements:

Table 3. Elements of module requirements
Name Description

module

The module name that is required by this requirement, as a string (required)

version

A version associated with this requirement, as a string (optional); this is ignored by the platform and is mainly useful for the purpose of documenting the version of the dependency that was present at build time

static

A boolean which indicates whether this dependency is optional, meaning the module can be loaded even if the dependency is not satisfied at run time; defaults to false

transitive

A boolean which indicates whether this dependency should be made readable to modules which depend on this module; defaults to false

In addition, the following more esoteric elements are supported for requirements:

Table 4. Less common elements of module requirements
Name Description

synthetic

A boolean value; set to true to set the ACC_SYNTHETIC flag on the requirement (optional)

mandated

A boolean value; set to true to set the ACC_MANDATED flag on the requirement (optional)

Module exports

Exported packages are described as a list of objects with the following elements:

Table 5. Elements of module exports
Name Description

package

The package name to export, as a string (required)

to

A list of target module names to export the module to; if not given, the package is exported to all dependent modules (optional)

In addition, the following more esoteric elements are supported for exports:

Table 6. Less common elements of module exports
Name Description

synthetic

A boolean value; set to true to set the ACC_SYNTHETIC flag on the export (optional)

mandated

A boolean value; set to true to set the ACC_MANDATED flag on the export (optional)

Provided services

A module can provide implementations of service APIs using the java.util.ServiceLoader mechanism. Provided services are described as a list of objects with the following elements:

Table 7. Elements of service providence
Name Description

serviceType

The service class name to provide, as a string (required)

with

A list of strings containing the class names of the service implementations (required)

Annotations

Module-level annotations can be provided in the YAML descriptor as objects with the following elements:

Table 8. Elements of module-level annotations
Name Description

type

The class name of the annotation type (required)

visible

A boolean value; set to true to specify that the annotation value is run-time visible (optional)

values

A map whose keys are the annotation parameter names and whose values are the annotation parameter values (optional)

Annotation value types are generally inferred from the value’s YAML type (which can be coerced using YAML schema tags if necessary).

Nested annotations, class values, and enum values are not yet supported, but will be supported in a future version.

YAML Example

You can define a module-info.yml file in your project’s base directory like this one:

Example module-info.yml file
name: blork.gadget.foo
version: 1.45 # this shows up in stack traces; useful for debugging
packages: # this can also be provided automatically; see below
    - blork.gadget.foo
    - blork.gadget.foo.impl
    - blork.gadget.foo.spi
requires:
    - module: blork.common
      version: 2.12  # this is documentation, not used by the run time
exports:
    - package: blork.gadget.foo
    - package: blork.gadget.foo.spi
      to:
          - blork.gadget.foo.plugin.special
provides:
    - serviceType: blork.gadget.foo.TheBlorkGadgetFooService
      with:
          - blork.gadget.foo.impl.BlorkFooImpl1
          - blork.gadget.foo.impl.BlorkFooImpl2
uses:
    - blork.common.FooService

You can add in other content according to the included schema.

Usage

This project is intended to be consumed either directly on the command line, or from a build system such as Maven.

Command line usage

The generator can be executed as a standalone JAR from the command line, like this:

java -jar module-info.jar [OPTION]...

Or like this:

java -p <path-to-directory-with-module-info.jar> -m io.github.dmlloyd.module-info [OPTION]...

The following command-line options are supported:

Table 9. Supported command line options
Short name Long name Default Description

-i

--module-info-yml

none

Optional - A string specifying the location of the input module-info.yml file

-o

--output-dir

none

Required - A string specifying the directory into which the generated module-info.class file should be placed

--class-path

none

Optional - The class path of the module (separated by : or ;, depending on platform) to examine for detecting requirements, packages, etc.

-n

--module-name

none

Optional - The module name to use, overriding the name given in the module-info.yml file

-v

--module-version

none

Optional - The module version to use, overriding the version given in the module-info.yml file

--add-mandatory

true

Optional - Add the mandatory java.base dependency to the module definition

--add-packages

true

Optional - Automatically add all packages found on the given class path

--add-exports

true

Optional - Automatically export all packages that do not contain a segment called _private or internal

--detect-uses

true

Optional - Automatically detect all service types used by this module

--detect-provides

true

Optional - Automatically add all entries found in META-INF/services on the class path to this module as provided services

--detect-version

false

Optional - Automatically set the module version based on information in META-INF/MANIFEST.MF, if any

--help

none

Print the help message and exit

Maven usage

The Maven artifact of this project also serves as a Maven plugin which will process your compiled project to produce the module-info.class file in the project output directory. The current version can be found at [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.github.dmlloyd.module-info/module-info/badge.png)](https://maven-badges.herokuapp.com/maven-central/io.github.dmlloyd.module-info/module-info).

The plugin will dynamically determine the correct descriptor values for most simple projects, including using a simple algorithm to derive a suitable module name from the project group and artifact ID, but the configuration can be fine-tuned as described below.

Note that there is presently no support for extracting module requirements from the project. Any module dependencies have to be explicitly listed in the module-info.yml file.

Maven configuration

The following properties are supported by the single generate goal, which is bound to the process-classes phase:

Table 10. Maven required parameters

Name

Type

Since

Description

<outputDirectory>

File

1.0

The directory where the module-info.class file should be installed.

Default value is: ${project.build.outputDirectory}

<classesDirectory>

File

1.0

The directory where class files can be read from.

Default value is: ${project.build.outputDirectory}

<moduleArtifactId>

String

1.0

The artifact ID to use to generate a module name, if none is given.

Default value is: ${project.artifactId}

<moduleGroupId>

String

1.0

The group ID to use to generate a module name, if none is given.

Default value is: ${project.groupId}

Table 11. Maven optional parameters

Name

Type

Since

Description

<moduleInfoYml>

File

1.0

The path to the module-info.yml file.

Default value is: ${project.build.sourceDirectory}/module-info.yml

<skip>

boolean

1.0

If set to true, the plugin is skipped; generally useful for overriding behavior from the command line.

Default value is: false

User property is: module-info.skip

<addPackages>

boolean

1.0

If set to true, all packages found in the project classes will be added to the module definition.

Default value is: true

User property is: module-info.add-packages

<addExports>

boolean

1.0

If set to true, all packages that do not contain a segment called _private or internal will be exported to dependents.

Default value is: true

User property is: module-info.add-exports

<moduleName>

String

1.0

Specify the module name to use. If not given, a module name is constructed from the project group and artifact ID.

User property is: module-info.module-name

<moduleVersion>

String

1.0

Specify the module version to use.

Default value is: ${project.version}

User property is: module-info.module-version

<addMandatory>

boolean

1.0

If true, add the mandatory java.base requirement.

Default value is: true

User property is: module-info.add-mandatory

<detectUses>

boolean

1.0

If true, attempt to automatically detect all service types used by this module.

Default value is: true

User property is: module-info.detect-uses

<detectProvides>

boolean

1.0

If true, automatically add all entries found in META-INF/services on the class path to this module as provided services.

Default value is: true

User property is: module-info.detect-provides

Maven usage example

Add a snippet like this to your pom.xml to get started:

Example Maven POM snippet
    <build>
        <plugins>
            <plugin>
                <groupId>io.github.dmlloyd.module-info</groupId>
                <artifactId>module-info</artifactId>
                <version>1.2</version>
                <executions>
                    <execution>
                        <id>module-info</id>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

Advanced case: shade plugin

The maven-shade-plugin has an unfortunate limitation in that it deletes any module-info.class from the target artifact, even if you carefully included all of the shaded packages in their final locations.

In order to work around this problem, a second goal is defined in this project for the case where the shade plugin is used. The goal simply re-adds the compiled module-info.class to the JAR. To use the goal, add this execution to the module-info plugin configuration:

Add an execution to re-add module-info.class
                    <execution>
                        <id>re-add-module-info</id>
                        <phase>package</phase>
                        <goals>
                            <goal>re-add</goal>
                        </goals>
                    </execution>

Building this project

This project is built with Maven. Since the project defines a plugin that is in turn used by itself, the build must be run twice: once to bootstrap the plugin, and once to build it with its own module-info.

Run both commands:

Commands to run to build this project
mvn clean install -Dbootstrap
mvn clean install

module-info-maven-plugin's People

Contributors

bobmcwhirter avatar dependabot[bot] avatar dmlloyd avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.