lingocoder
lingocoder


mrjar mrJar
Modular MRJAR Files Made Easy

  Due to a breaking change in Gradle 5.6.1, current versions of mrJar are confirmed to work only with Gradle versions 5.0.0 to 5.5.1  

  Usage:  

    /* (1) Decide which type of module artifact your project needs to produce and proceed accordingly         */
    /*                                                                                                        */
    /*     (a) A Single-Release Jar File that targets a single JDK release and packages a single module       */
    /*         • DO NOT set any JDK release environment variables. Proceed to (2)                             */
    /*                                                                                                        */
    /*     (b) A Multi-Release Jar File that targets two or more Java 9+ releases.                            */
    /*         • Set two environment variables. One named JAVA_8 and the other named JAVA_9.                  */
    /*           They must refer to the file system installations of JDK version 8 and 9 respectively.        */
    /*                                                                                                        */
    /* (2) Apply the mrjar plugin using the plugins DSL.                                                      */
    plugins{
        id 'com.lingocoder.mrjar' version '0.0.5'
    }
		
    /* (3) Configure repositories. jcenter is preferred by Gradle.org. */
    repositories {jcenter()}

    dependencies {
        /* Declare your api|implementation|testImplementation dependencies required by your system. */
        api 'com.example:foo:0.0.0'
        implementation 'net.bar:etc-etc:18.0'
        ...     
    }

    mrjar {
        /* (4) Tell mrjar which releases you want your MRJAR File to support                  */
        /*     • this property is mandatory. The values must be Gradle's version enum types   */
        releases = [JavaVersion.VERSION_12, JavaVersion_11]
 
        /* (5) Optionally, you can tell mrjar to create the packages you need                 */
        /*     • each package in the list will be created in each release src directory       */
        packages = ['org.example.foo', 'io.another.one',...]

        /* (6) Optionally, tell mrjar you want a modular MRJAR                                */
        /*     • or just the existence of a module-info.java file has the same effect         */
        isModular = true (or false)

        /* (7) Optionally, tell mrjar to use a specific name for your module.                 */
        /*     • by default, mrJar uses the project name and version                          */
        moduleName = 'foo.bar'

        /* (8) Optionally — or, mandatorily if you're using Gradle's Application              */
        /*     Plugin to execute a Java application bundled in your module — tell             */
        /*     mrjar the binary name of the class you want the Application Plugin to run      */
        /*     • the value of this property will automatically propagate to the               */
        /*       Application Plugin's :run task                                               */
        main = 'com.acme.main.JavaMain'
    }
  From the command line, run:  

    $ ./gradlew :mrinit
 What :mrinit gets you is a source directory hierarchy for each release you specified. So for the above example, folders at src/main/java11 and src/main/java12 will have been created. After that initial setup, you will, of course, need to populate the source directories with the source code for each respective release to be supported by your MRJAR. And also, optionally, any module-info.java files you might optionally need; if you're going the modular jar1 route — a single-release module that is just one single library per jar file is not an uncommon use case.  

 After you have all your release source folders, your packages hierarchy, and naturally, your actual source code in place, that's pretty much it. The :mrinit task is more or less a one-time deal; just to initialize your releases in preparation for their eventual bundling into the artifact your project will ultimately produce. After you run :mrinit the one time, you then simply proceed with your typical test/develop/build cycle exactly as you ordinarily would. Then, when you want to publish the artifacts of your project, you do that too exactly like you normally would. Nothing different:

    $ ./gradlew :publish
 So for example, the mrJar plugin uses itself to build itself as a modular MRJAR File. As I developed the plugin, I did the steps outlined above. Because I used Gradle's Java Plugin Development Plugin, I ran the :publish task often. The output of that built-in task was my plugin's jar as a modular MRJAR File. Which I used during development on the plugin itself (dog-fooding). Likewise, when I published the plugin to Gradle's Plugin Portal. In that use case, you just use the Plugin Publishing Plugin as usual:

    $ ./gradlew :publishPlugin
 In the presense of any plugin that relies on Gradle's built-in :jar task, mrJar in the mix enhances :jar to be MRJAR-capable. mrJar itself, however, does not provide a specific task that must be explictly executed to create a module or an MRJAR.

 Any and all questions or suggestions are welcomed. Please do not hesitate to message me with anything. I'd be thrilled to hear from you.

__________
1It's important to bear in mind that Modular Jars are distinct from Multi-Release Jars. They are related. But they are not the same. You can have one, and it will not neccessarily mean you also have the other.