{"id":90144,"date":"2019-03-30T15:15:52","date_gmt":"2019-03-30T13:15:52","guid":{"rendered":"https:\/\/www.javacodegeeks.com\/?p=90144"},"modified":"2019-03-28T09:55:06","modified_gmt":"2019-03-28T07:55:06","slug":"building-java-6-8-libraries-jpms-gradle","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2019\/03\/building-java-6-8-libraries-jpms-gradle.html","title":{"rendered":"Building Java 6-8 Libraries for JPMS in Gradle"},"content":{"rendered":"<p>Find out how to use <a href=\"https:\/\/gradle.org\/\">Gradle<\/a> to build Java 6-8 libraries that support JPMS (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Java_Platform_Module_System\">Java Platform Module System<\/a>) by providing Java 9 <code>module-info.class<\/code>.<\/p>\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n<p>If you need introduction to JPMS itself, check out <a href=\"https:\/\/www.oracle.com\/corporate\/features\/understanding-java-9-modules.html\">this nice overview<\/a>.<\/p>\n<p>This post is primarily targeted at Java library maintainers.<\/p>\n<p>Any such maintainer has to make a choice of which JDK to target:<\/p>\n<ul class=\"wp-block-list\">\n<li>Targeting the newest JDKs (<a href=\"https:\/\/openjdk.java.net\/projects\/jdk\/11\/\">JDK 11<\/a>, or just released <a href=\"https:\/\/openjdk.java.net\/projects\/jdk\/12\/\">JDK 12<\/a>) provides the developers and users with access to new APIs and more functionality.<\/li>\n<li>However, it prevents the library to be used by all those users who are stuck on older JDKs.\n<ul>\n<li>And those older JDKs are still <strong>very<\/strong> popular, <a href=\"https:\/\/www.baeldung.com\/java-in-2018\">taking ~95% share in 2018<\/a>, and\u00a0<a href=\"https:\/\/www.infoq.com\/news\/2018\/12\/java-2019-predictions\">predicted to take ~90% in 2019<\/a>. Especially the popularity of JDK 8 (> 80% share) makes it a de-facto standard for now.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>So the latter is rightly a <em>deciding factor<\/em> for many library maintainers. For example, <a href=\"http:\/\/www.vavr.io\/\">vavr<\/a> 1.0 <a href=\"http:\/\/blog.vavr.io\/i-believe-in-java-modules\/\">was intended to target JDK 11<\/a>, but <a href=\"http:\/\/blog.vavr.io\/purifying-the-api-surface-area\/#modularization\">will ultimately target JDK 8<\/a>.<\/p>\n<p>Still, it\u2019s advisable to add <em>some<\/em> support for JPMS in the hope that it will see wide adoption in future (I\u2019d say 5+ years from now).<a href=\"https:\/\/blog.joda.org\/2018\/03\/jpms-negative-benefits.html\">Stephen Colebourne describes<\/a> three options here:<\/p>\n<ol class=\"wp-block-list\">\n<li>Do nothing (not recommended).<\/li>\n<li>Minimum: add an <code>Automatic-Module-Name<\/code> entry in your <code>MANIFEST.MF<\/code> file.<\/li>\n<li>Optimum: add a <code>module-info.class<\/code> targeting JDK 9+ while providing all the remaining classes targeting JDK 6-8<sup>*<\/sup>.<\/li>\n<\/ol>\n<p>Here, we\u2019ll delve into how to achieve option 3 (the optimum).<\/p>\n<p><em><sup>*<\/sup> I write about JDK 6-8 (and not e.g. JDK 5-8) because, in JDK 11, <code><a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/11\/tools\/javac.html\">javac<\/a><\/code>\u2018s <code>--release<\/code> option is limited to range 6-11.<\/em><\/p>\n<h2 class=\"wp-block-heading\">Justification<\/h2>\n<p>Before we delve into \u201chow\u201d, though, let\u2019s skim over \u201cwhy\u201d.<\/p>\n<p>Why is it worth bothering with JPMS at all? Primarily because JPMS:<\/p>\n<ul class=\"wp-block-list\">\n<li>provides <a href=\"https:\/\/www.oracle.com\/corporate\/features\/understanding-java-9-modules.html\">strong encapsulation<\/a>,<\/li>\n<li>prevents introducing <a href=\"https:\/\/blog.codefx.org\/java\/java-9-migration-guide\/#Split-Packages\">split packages<\/a>,<\/li>\n<li>ensures <a href=\"https:\/\/stackoverflow.com\/a\/45717031\/2032415\">faster class loading<\/a>.<\/li>\n<\/ul>\n<p>To sum up, JPMS is <em>really cool<\/em> (more <a href=\"https:\/\/stackoverflow.com\/a\/44574088\/2032415\">here<\/a>), and it\u2019s in our best interest to encourage its adoption!<\/p>\n<p>So I encourage the maintainers of Java 6-8 libraries to make the most of JPMS:<\/p>\n<ul class=\"wp-block-list\">\n<li>for themselves, by compiling <code>module-info.java<\/code> against the JDK 6-8 classes of its module and against other modules,<\/li>\n<li>for their users, by providing <code>module-info.class<\/code> for the library to work well on module-path.<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">Possible Behavior<\/h2>\n<h3 class=\"wp-block-heading\">Location of <code>module-info.java<\/code><\/h3>\n<p>There are two places where <code>module-info.java<\/code> can be located:<\/p>\n<ol class=\"wp-block-list\">\n<li>with all the other classes, in <code>src\/main\/java<\/code>,<\/li>\n<li>in a separate \u201csource set\u201d, e.g. in <code>src\/main\/java9<\/code>.<\/li>\n<\/ol>\n<p>I prefer option 1, because it just seems more natural.<\/p>\n<h3 class=\"wp-block-heading\">Location of <code>module-info.class<\/code><\/h3>\n<p>There are two places where <code>module-info.class<\/code>&nbsp;can end up:<\/p>\n<ol class=\"wp-block-list\">\n<li>in the root output directory, with all the other classes,<\/li>\n<li>in&nbsp;<code>META-INF\/versions\/9<\/code>&nbsp;(Multi-Release JAR, AKA&nbsp;<a href=\"https:\/\/openjdk.java.net\/jeps\/238\">MRJAR<\/a>)<\/li>\n<\/ol>\n<p>Having read a&nbsp;<a href=\"https:\/\/blog.gradle.org\/mrjars\">post on MRJARs<\/a> by C\u00e9dric Champeau, I\u2019m rather suspicious of MRJARs, and so I prefer option 1.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<p>Note, however, that <a href=\"https:\/\/github.com\/java9-modularity\/gradle-modules-plugin\/issues\/72#issuecomment-475175699\">Gunnar Morling reports<\/a> having had some issues with option 1. On the other hand, I hope that 1.5 years from the release of JDK 9, all major libraries are already patched to properly handle <code>module-info.class<\/code>.<\/p>\n<h2 class=\"wp-block-heading\">Example Libraries per Build Tool<\/h2>\n<p>This section contains a few examples of libraries that provide <code>module-info.class<\/code> while targeting JDK 6-8.<\/p>\n<h3 class=\"wp-block-heading\">Ant<\/h3>\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/rzwitserloot\/lombok\/blob\/fd9045dac2a3d9b26125b8ccc865b23d8f7cd8d4\/build.xml#L251\">Lombok<\/a> (JDK 6 main + JDK 9 <code>module-info.class<\/code>)<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">Maven<\/h3>\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/ThreeTen\/threeten-extra\/blob\/63f784b0d4e280654d7add5b9d31e6e6bb4cf16f\/pom.xml#L601\">ThreeTen-extra<\/a> (JDK 8 main + JDK 9 <code>module-info.class<\/code>)<\/li>\n<li><a href=\"https:\/\/github.com\/google\/gson\/blob\/5bbc768fa6cd3e8a3a7bebf52b0ac1e4c6e0bd12\/pom.xml#L64\">Google Gson<\/a> \u2013 not released yet (JDK 6 main + JDK 9 <code>module-info.class<\/code>)<\/li>\n<li><a href=\"https:\/\/github.com\/qos-ch\/slf4j\/blob\/fc7bf4dee401b8c1a3ddfd5bb9a7b01ac1febfec\/pom.xml#L212\">SLF4J<\/a> \u2013 not released yet (JDK 6 main + JDK 9 <code>module-info.class<\/code>&nbsp;in&nbsp;<code>META-INF\/versions\/9<\/code>)<\/li>\n<\/ul>\n<p>Note that <a href=\"https:\/\/maven.apache.org\/plugins\/maven-compiler-plugin\/\">Maven Compiler Plugin<\/a> provides an <a href=\"https:\/\/maven.apache.org\/plugins\/maven-compiler-plugin\/examples\/module-info.html\">example of how to provide such support<\/a>.<\/p>\n<h3 class=\"wp-block-heading\">Gradle<\/h3>\n<p>I haven\u2019t found any popular libraries that provide such support using Gradle (please comment if you know any). I only know of <a href=\"http:\/\/www.vavr.io\/\">vavr<\/a> trying to do this (<a href=\"https:\/\/github.com\/vavr-io\/vavr\/issues\/2230\">#2230<\/a>).<\/p>\n<h2 class=\"wp-block-heading\">Existing Approaches in Gradle<\/h2>\n<h3 class=\"wp-block-heading\">ModiTect<\/h3>\n<p><a href=\"https:\/\/github.com\/moditect\/moditect\">ModiTect<\/a> (by <a href=\"https:\/\/github.com\/gunnarmorling\">Gunnar Morling<\/a>) and its <a href=\"https:\/\/github.com\/moditect\/moditect-gradle-plugin\">Gradle plugin<\/a> (by <a href=\"https:\/\/github.com\/siordache\">Serban Iordache<\/a>) have some <a href=\"https:\/\/github.com\/java9-modularity\/gradle-modules-plugin\/issues\/72#issuecomment-475408988\">really cool features<\/a>. In essence, ModiTect <a href=\"https:\/\/github.com\/moditect\/moditect-gradle-plugin#generatemoduleinfo\">generates<\/a>&nbsp;<code>module-info.class<\/code> without the use of <code>javac<\/code>, based on a special notation or directly from <code>module-info.java<\/code>.<\/p>\n<p>However, in case of direct generation from <code>module-info.java<\/code>, ModiTect effectively duplicates what <code>javac<\/code> does while introducing issues of its own (e.g. <a href=\"https:\/\/github.com\/moditect\/moditect\/issues\/90\">#90<\/a>). That\u2019s why I feel it\u2019s not the best tool here.<\/p>\n<h3 class=\"wp-block-heading\">Badass Jar plugin<\/h3>\n<p><a href=\"https:\/\/github.com\/siordache\">Serban Iordache<\/a>&nbsp;also created a&nbsp;<a href=\"https:\/\/github.com\/beryx\/badass-jar-plugin\">Gradle plugin<\/a>&nbsp;that lets one \u201cseamlessly create modular jars that target a Java release before 9\u201d.<\/p>\n<p>It looks quite nice, however:<\/p>\n<ul class=\"wp-block-list\">\n<li>in order to build the proper JAR and validate <code>module-info.java<\/code>, the Gradle build has to be run twice,<\/li>\n<li>it doesn\u2019t use <code>javac<\/code>\u2018s <code>--release<\/code> option, which guarantees that only the right APIs are referenced,<\/li>\n<li>it doesn\u2019t use <code>javac<\/code> to compile <code>module-info.java<\/code>.<\/li>\n<\/ul>\n<p>Again, I feel it\u2019s not the right tool here.<\/p>\n<h3 class=\"wp-block-heading\">JpmsGradlePlugin<\/h3>\n<p>This is my most recent find: <a href=\"https:\/\/github.com\/xzel23\/JpmsGradlePlugin\">JpmsGradlePlugin<\/a> by <a href=\"https:\/\/github.com\/xzel23\">Axel Howind<\/a>.<\/p>\n<p>The plugin does some nice things (e.g. excluding <code>module-info.java<\/code> from <code>javadoc<\/code> task), however:<\/p>\n<ul class=\"wp-block-list\">\n<li>it too doesn\u2019t use <code>javac<\/code>\u2018s <code>--release<\/code> option,<\/li>\n<li>it doesn\u2019t support Java modularity fully (e.g. module patching),<\/li>\n<li>it doesn\u2019t feel mature enough (code <a href=\"https:\/\/github.com\/xzel23\/JpmsGradlePlugin\/blob\/a01863368957569ddd6eb64c0115b6098b9b4e52\/JpmsGradlePlugin\/src\/main\/java\/com\/dua3\/gradle\/jpms\/task\/ModuleInfoJava.java#L40\">hard to follow<\/a>, non-standard behavior like <a href=\"https:\/\/github.com\/xzel23\/JpmsGradlePlugin\/blob\/master\/JpmsGradlePlugin\/src\/main\/java\/com\/dua3\/gradle\/jpms\/task\/TaskHelper.java#L61\">calling <code>javac<\/code> directly<\/a>).<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">Proposed Approach in Gradle<\/h2>\n<h3 class=\"wp-block-heading\">Gradle Script<\/h3>\n<p>Initially, I <a href=\"https:\/\/stackoverflow.com\/q\/55100737\/2032415\">wanted to do this by adding a custom source set<\/a>. However, it turned out that such an approach would introduce unnecessary <a href=\"https:\/\/docs.gradle.org\/current\/userguide\/java_plugin.html#java_source_set_configurations\">configurations<\/a> and <a href=\"https:\/\/docs.gradle.org\/current\/userguide\/java_plugin.html#java_source_set_tasks\">tasks<\/a>, while what we really need is only one extra task, \u201chooked\u201d properly into the <a href=\"http:\/\/melix.github.io\/blog\/2018\/09\/gradle-lifecycle.html\">build lifecycle<\/a>.<\/p>\n<p>As a result, I came up with the following:<\/p>\n<ol class=\"wp-block-list\">\n<li>Configure <code><a href=\"https:\/\/docs.gradle.org\/current\/userguide\/java_plugin.html#compilejava\">compileJava<\/a><\/code> to:\n<ul>\n<li><a href=\"https:\/\/docs.gradle.org\/current\/dsl\/org.gradle.api.tasks.compile.JavaCompile.html#org.gradle.api.tasks.compile.JavaCompile:exclude(java.lang.String[])\">exclude<\/a> <code>module-info.java<\/code>,<\/li>\n<li>use <code>--release 6\/7\/8<\/code> option. <\/li>\n<\/ul>\n<\/li>\n<li>Add a new <code><a href=\"https:\/\/docs.gradle.org\/current\/dsl\/org.gradle.api.tasks.compile.JavaCompile.html\">JavaCompile<\/a><\/code> task named <code>compileModuleInfoJava<\/code> and configure it to:\n<ul>\n<li><a href=\"https:\/\/docs.gradle.org\/current\/dsl\/org.gradle.api.tasks.compile.JavaCompile.html#org.gradle.api.tasks.compile.JavaCompile:include(java.lang.String[])\">include<\/a> only <code>module-info.java<\/code>,<\/li>\n<li>use <code>--release 9<\/code> option,<\/li>\n<li>use the <a href=\"https:\/\/docs.gradle.org\/current\/dsl\/org.gradle.api.tasks.compile.JavaCompile.html#org.gradle.api.tasks.compile.JavaCompile:classpath\">classpath<\/a> of <code>compileJava<\/code> as <code>--module-path<\/code><sup>*<\/sup>,<\/li>\n<li>use the <a href=\"https:\/\/docs.gradle.org\/current\/dsl\/org.gradle.api.tasks.compile.JavaCompile.html#org.gradle.api.tasks.compile.JavaCompile:destinationDir\">destination directory<\/a> of <code>compileJava<\/code><sup>*<\/sup>,<\/li>\n<li><a href=\"https:\/\/docs.gradle.org\/current\/dsl\/org.gradle.api.Task.html#org.gradle.api.Task:dependsOn(java.lang.Object[])\">depend on<\/a> <code>compileJava<\/code><sup>*<\/sup>.\n<\/li>\n<\/ul>\n<\/li>\n<li>Configure <code><a href=\"https:\/\/docs.gradle.org\/current\/userguide\/java_plugin.html#sec:java_tasks\">classes<\/a><\/code> task to depend on <code>compileModuleInfoJava<\/code>.<\/li>\n<\/ol>\n<p>The above, expressed as a Gradle script in Groovy DSL, can be found in <a href=\"https:\/\/stackoverflow.com\/a\/55143699\/2032415\">this Stack Overflow answer of mine<\/a>.<\/p>\n<p><em><sup>*<\/sup> These three steps are necessary for <code>compileModuleInfoJava<\/code> to see classes compiled by <code>compileJava<\/code>. Otherwise, <code>javac<\/code> wouldn\u2019t be able to compile <code>module-info.java<\/code> due to unresolved references. Note that in such configuration, every class is <strong>compiled just once<\/strong> (unlike with the recommended <a href=\"https:\/\/maven.apache.org\/plugins\/maven-compiler-plugin\/examples\/module-info.html\">Maven Compiler Plugin configuration<\/a>).<\/em><\/p>\n<p>Unfortunately, such configuration:<\/p>\n<ul class=\"wp-block-list\">\n<li>is not easily reusable across repositories,<\/li>\n<li>doesn\u2019t support Java modularity fully.<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">Gradle Modules Plugin<\/h3>\n<p>Finally, there\u2019s a plugin (<a href=\"https:\/\/github.com\/java9-modularity\/gradle-modules-plugin\">Gradle Modules Plugin<\/a>) that adds full support for JPMS to Gradle (created by the authors of <em><a href=\"https:\/\/javamodularity.com\/\">Java 9 Modularity<\/a><\/em>, <a href=\"https:\/\/twitter.com\/Sander_Mak\">Sander Mak<\/a> and <a href=\"https:\/\/twitter.com\/pbakker\">Paul Bekker<\/a>).<\/p>\n<p>This plugin only lacks support for the scenario described in this post. Therefore, I decided to:<\/p>\n<ul class=\"wp-block-list\">\n<li>file a feature request with this plugin: <a href=\"https:\/\/github.com\/java9-modularity\/gradle-modules-plugin\/issues\/72\">#72<\/a><\/li>\n<li>provide a Pull Request with a <strong>complete<\/strong> implementation of #72 (as a \u201cproof of concept\u201d): <a href=\"https:\/\/github.com\/java9-modularity\/gradle-modules-plugin\/pull\/73\">#73<\/a><\/li>\n<\/ul>\n<p>I tried hard to make these high-quality contributions. The initial feedback was <a href=\"https:\/\/twitter.com\/pbakker\/status\/1108987207002423296\">very welcome<\/a> (even <a href=\"https:\/\/twitter.com\/mreinhold\">Mark Reinhold<\/a> liked this!). Thank you!<\/p>\n<p>Now, I\u2019m patiently waiting for <a href=\"https:\/\/github.com\/java9-modularity\/gradle-modules-plugin\/issues\/72#issuecomment-475513738\">further feedback<\/a> (and potential improvement requests) before the PR can be (hopefully) merged. <\/p>\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n<p>In this post, I\u2019ve shown how to build Java 6-8 libraries with Gradle so that <code>module-info.java<\/code> is compiled to JDK 9 format (JPMS support), while all the other classes are compiled to JDK 6-8 format.<\/p>\n<p>I\u2019ve also recommended to use <a href=\"https:\/\/github.com\/java9-modularity\/gradle-modules-plugin\">Gradle Modules Plugin<\/a> for such configuration (as soon as <a href=\"https:\/\/github.com\/java9-modularity\/gradle-modules-plugin\/pull\/73\">my PR gets merged<\/a> and a new plugin version <a href=\"https:\/\/github.com\/java9-modularity\/gradle-modules-plugin\/releases\">gets released<\/a>).<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td>\n<p>Published on Java Code Geeks with permission by Tomasz Linkowski, partner at our <a href=\"\/\/www.javacodegeeks.com\/join-us\/jcg\/\" target=\"_blank\" rel=\"noopener noreferrer\">JCG program<\/a>. See the original article here: <a href=\"https:\/\/blog.tlinkowski.pl\/2019\/building-java-6-8-libraries-for-jpms-in-gradle\/\" target=\"_blank\" rel=\"noopener noreferrer\">Building Java 6-8 Libraries for JPMS in Gradle<\/a><\/p>\n<p>Opinions expressed by Java Code Geeks contributors are their own.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Find out how to use Gradle to build Java 6-8 libraries that support JPMS (Java Platform Module System) by providing Java 9 module-info.class. Introduction If you need introduction to JPMS itself, check out this nice overview. This post is primarily targeted at Java library maintainers. Any such maintainer has to make a choice of which &hellip;<\/p>\n","protected":false},"author":73716,"featured_media":129,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[484,1205,402],"class_list":["post-90144","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-gradle","tag-groovy","tag-open-source"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Building Java 6-8 Libraries for JPMS in Gradle - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Interested to learn about Java 6-8 Libraries? Check our article explaining how how to use Gradle to build Java 6-8 libraries that support JPMS\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2019\/03\/building-java-6-8-libraries-jpms-gradle.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Building Java 6-8 Libraries for JPMS in Gradle - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Interested to learn about Java 6-8 Libraries? Check our article explaining how how to use Gradle to build Java 6-8 libraries that support JPMS\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2019\/03\/building-java-6-8-libraries-jpms-gradle.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2019-03-30T13:15:52+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/gradle-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Tomasz Linkowski\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@t_linkowski\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Tomasz Linkowski\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/03\\\/building-java-6-8-libraries-jpms-gradle.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/03\\\/building-java-6-8-libraries-jpms-gradle.html\"},\"author\":{\"name\":\"Tomasz Linkowski\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/aeb886d1af1e697dde4f89ed76e6d020\"},\"headline\":\"Building Java 6-8 Libraries for JPMS in Gradle\",\"datePublished\":\"2019-03-30T13:15:52+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/03\\\/building-java-6-8-libraries-jpms-gradle.html\"},\"wordCount\":1138,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/03\\\/building-java-6-8-libraries-jpms-gradle.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/gradle-logo.jpg\",\"keywords\":[\"Gradle\",\"Groovy\",\"Open Source\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/03\\\/building-java-6-8-libraries-jpms-gradle.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/03\\\/building-java-6-8-libraries-jpms-gradle.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/03\\\/building-java-6-8-libraries-jpms-gradle.html\",\"name\":\"Building Java 6-8 Libraries for JPMS in Gradle - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/03\\\/building-java-6-8-libraries-jpms-gradle.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/03\\\/building-java-6-8-libraries-jpms-gradle.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/gradle-logo.jpg\",\"datePublished\":\"2019-03-30T13:15:52+00:00\",\"description\":\"Interested to learn about Java 6-8 Libraries? Check our article explaining how how to use Gradle to build Java 6-8 libraries that support JPMS\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/03\\\/building-java-6-8-libraries-jpms-gradle.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/03\\\/building-java-6-8-libraries-jpms-gradle.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/03\\\/building-java-6-8-libraries-jpms-gradle.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/gradle-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/gradle-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/03\\\/building-java-6-8-libraries-jpms-gradle.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Building Java 6-8 Libraries for JPMS in Gradle\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/aeb886d1af1e697dde4f89ed76e6d020\",\"name\":\"Tomasz Linkowski\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/7c7c7d3e6219a951c029f5aee439ff9d0b9784d77bb8e0ef4a180b21baa640dc?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/7c7c7d3e6219a951c029f5aee439ff9d0b9784d77bb8e0ef4a180b21baa640dc?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/7c7c7d3e6219a951c029f5aee439ff9d0b9784d77bb8e0ef4a180b21baa640dc?s=96&d=mm&r=g\",\"caption\":\"Tomasz Linkowski\"},\"description\":\"Tomasz is an enthusiast of clean coding and software craftsmanship, who is particularly interested in problem domain modeling &amp; API design\",\"sameAs\":[\"http:\\\/\\\/blog.tlinkowski.pl\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/tomaszlinkowski\\\/\",\"https:\\\/\\\/x.com\\\/t_linkowski\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/tomasz-linkowski\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Building Java 6-8 Libraries for JPMS in Gradle - Java Code Geeks","description":"Interested to learn about Java 6-8 Libraries? Check our article explaining how how to use Gradle to build Java 6-8 libraries that support JPMS","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2019\/03\/building-java-6-8-libraries-jpms-gradle.html","og_locale":"en_US","og_type":"article","og_title":"Building Java 6-8 Libraries for JPMS in Gradle - Java Code Geeks","og_description":"Interested to learn about Java 6-8 Libraries? Check our article explaining how how to use Gradle to build Java 6-8 libraries that support JPMS","og_url":"https:\/\/www.javacodegeeks.com\/2019\/03\/building-java-6-8-libraries-jpms-gradle.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2019-03-30T13:15:52+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/gradle-logo.jpg","type":"image\/jpeg"}],"author":"Tomasz Linkowski","twitter_card":"summary_large_image","twitter_creator":"@t_linkowski","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Tomasz Linkowski","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2019\/03\/building-java-6-8-libraries-jpms-gradle.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/03\/building-java-6-8-libraries-jpms-gradle.html"},"author":{"name":"Tomasz Linkowski","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/aeb886d1af1e697dde4f89ed76e6d020"},"headline":"Building Java 6-8 Libraries for JPMS in Gradle","datePublished":"2019-03-30T13:15:52+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/03\/building-java-6-8-libraries-jpms-gradle.html"},"wordCount":1138,"commentCount":1,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/03\/building-java-6-8-libraries-jpms-gradle.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/gradle-logo.jpg","keywords":["Gradle","Groovy","Open Source"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2019\/03\/building-java-6-8-libraries-jpms-gradle.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2019\/03\/building-java-6-8-libraries-jpms-gradle.html","url":"https:\/\/www.javacodegeeks.com\/2019\/03\/building-java-6-8-libraries-jpms-gradle.html","name":"Building Java 6-8 Libraries for JPMS in Gradle - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/03\/building-java-6-8-libraries-jpms-gradle.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/03\/building-java-6-8-libraries-jpms-gradle.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/gradle-logo.jpg","datePublished":"2019-03-30T13:15:52+00:00","description":"Interested to learn about Java 6-8 Libraries? Check our article explaining how how to use Gradle to build Java 6-8 libraries that support JPMS","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/03\/building-java-6-8-libraries-jpms-gradle.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2019\/03\/building-java-6-8-libraries-jpms-gradle.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2019\/03\/building-java-6-8-libraries-jpms-gradle.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/gradle-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/gradle-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2019\/03\/building-java-6-8-libraries-jpms-gradle.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Building Java 6-8 Libraries for JPMS in Gradle"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/aeb886d1af1e697dde4f89ed76e6d020","name":"Tomasz Linkowski","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/7c7c7d3e6219a951c029f5aee439ff9d0b9784d77bb8e0ef4a180b21baa640dc?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/7c7c7d3e6219a951c029f5aee439ff9d0b9784d77bb8e0ef4a180b21baa640dc?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/7c7c7d3e6219a951c029f5aee439ff9d0b9784d77bb8e0ef4a180b21baa640dc?s=96&d=mm&r=g","caption":"Tomasz Linkowski"},"description":"Tomasz is an enthusiast of clean coding and software craftsmanship, who is particularly interested in problem domain modeling &amp; API design","sameAs":["http:\/\/blog.tlinkowski.pl\/","https:\/\/www.linkedin.com\/in\/tomaszlinkowski\/","https:\/\/x.com\/t_linkowski"],"url":"https:\/\/www.javacodegeeks.com\/author\/tomasz-linkowski"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/90144","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/73716"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=90144"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/90144\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/129"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=90144"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=90144"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=90144"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}