From fa2f27ee420f73a0411377f1728387d8438b35f9 Mon Sep 17 00:00:00 2001 From: Akira Ajisaka Date: Sat, 10 Jan 2026 03:21:41 +0900 Subject: [PATCH 01/12] [WIP] HADOOP-19785. mvn site fails in JDK17 --- pom.xml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 8a4688a74a3d59..0378df07a43478 100644 --- a/pom.xml +++ b/pom.xml @@ -100,14 +100,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/x 2.8.1 - 3.9.1 + 3.21.0 1.5 1.7 2.4 3.8.1 3.5.0 2.0.0 - 3.0.1 + 3.12.0 1.5 1.5 3.0.1 @@ -677,9 +677,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/x aggregate - 1024m true false + true ${maven.compile.source} ${maven.compile.encoding} ${project.build.directory}/site @@ -721,7 +721,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/x org.apache.hadoop:hadoop-annotations - + + + org.apache.hadoop + hadoop-hdfs + ${project.version} + tests + + aggregate From 04b29403d9e101e7b5461d643b6bc7a6ada79772 Mon Sep 17 00:00:00 2001 From: Akira Ajisaka Date: Tue, 20 Jan 2026 10:42:00 +0900 Subject: [PATCH 02/12] Switch to default doclet --- pom.xml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pom.xml b/pom.xml index 0378df07a43478..bc39c4f4068ac1 100644 --- a/pom.xml +++ b/pom.xml @@ -704,15 +704,6 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/x org.apache.hadoop.yarn* - org.apache.hadoop.classification.tools.IncludePublicAnnotationsStandardDoclet - - - org.apache.hadoop - hadoop-annotations - ${project.version} - - - true false From cf1acb595076e83a242bd5633039d3b46b6e3c47 Mon Sep 17 00:00:00 2001 From: Akira Ajisaka Date: Tue, 20 Jan 2026 11:18:58 +0900 Subject: [PATCH 03/12] Fix javadoc errors --- .../manifest/ManifestCommitterConstants.java | 3 +-- .../impl/ManifestStoreOperations.java | 2 +- .../controller/AppDetailsController.java | 27 ++++++++++++++----- .../controller/AppListController.java | 17 +++++++++--- .../controller/AppStoreController.java | 17 +++++++++--- .../yarn/service/api/records/Component.java | 2 -- 6 files changed, 49 insertions(+), 19 deletions(-) diff --git a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/lib/output/committer/manifest/ManifestCommitterConstants.java b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/lib/output/committer/manifest/ManifestCommitterConstants.java index 8f359e45000f30..716e7b6e2f347b 100644 --- a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/lib/output/committer/manifest/ManifestCommitterConstants.java +++ b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/lib/output/committer/manifest/ManifestCommitterConstants.java @@ -221,7 +221,7 @@ public final class ManifestCommitterConstants { public static final boolean OPT_DELETE_TARGET_FILES_DEFAULT = false; /** - * Name of the factory: {@value}. + * Name of the factory. */ public static final String MANIFEST_COMMITTER_FACTORY = ManifestCommitterFactory.class.getName(); @@ -235,7 +235,6 @@ public final class ManifestCommitterConstants { /** * Default classname of the store operations. - * Value: {@value}. */ public static final String STORE_OPERATIONS_CLASS_DEFAULT = ManifestStoreOperationsThroughFileSystem.class.getName(); diff --git a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/lib/output/committer/manifest/impl/ManifestStoreOperations.java b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/lib/output/committer/manifest/impl/ManifestStoreOperations.java index 03e3ce0f0ade01..a7a72cda296e52 100644 --- a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/lib/output/committer/manifest/impl/ManifestStoreOperations.java +++ b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/lib/output/committer/manifest/impl/ManifestStoreOperations.java @@ -69,7 +69,7 @@ public void bindToFileSystem(FileSystem fileSystem, Path path) throws IOExceptio /** * Is a path a file? Used during directory creation. - * The is a copy & paste of FileSystem.isFile(); + * The is a copy and paste of FileSystem.isFile(); * {@code StoreOperationsThroughFileSystem} calls into * the FS direct so that stores which optimize their probes * can save on IO. diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/controller/AppDetailsController.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/controller/AppDetailsController.java index 63aefa615ffd4b..686f07fa4714d4 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/controller/AppDetailsController.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/controller/AppDetailsController.java @@ -52,6 +52,7 @@ public AppDetailsController() { /** * List detail information about the deployed application. * + *
{@code
    * @apiGroup AppDetailController
    * @apiName getDetails
    * @api {get} /app_details/config/{id}  Check config of application instance.
@@ -113,8 +114,10 @@ public AppDetailsController() {
    *           }
    *        }
    *     }
-   * @param id - Application ID
-   * @return application entry-
+   * }
+ * + * @param id Application ID + * @return application entry */ @Path("config/{id}") @GET @@ -127,10 +130,12 @@ public AppEntry getDetails(@PathParam("id") String id) { /** * Check application status. * + *
{@code
    * @apiGroup AppDetailController
    * @apiName getStatus
    * @api {get} /app_details/status/{id}  Check status of application instance.
    * @apiParam {String} id Application ID to check.
+   * @apiSuccess {Object} text Give status
    * @apiSuccessExample {json} Success-Response:
    *     HTTP/1.1 200 OK
    *     {
@@ -195,8 +200,9 @@ public AppEntry getDetails(@PathParam("id") String id) {
    *           }
    *        }
    *     }
-   * @apiSuccess {Object} text Give status
-   * @param id - Application ID
+   * }
+ * + * @param id Application ID * @return application entry */ @Path("status/{id}") @@ -213,13 +219,16 @@ public AppEntry getStatus(@PathParam("id") String id) { /** * Stop an application. * + *
{@code
    * @apiGroup AppDetailController
    * @apiName stopApp
    * @api {post} /app_details/stop/{id}  Stop one instance of application.
    * @apiParam {String} id Application ID to stop.
    * @apiSuccess {String} text Give deployment status
    * @apiError BadRequest Requested application does not stop.
-   * @param id - Application ID
+   * }
+ * + * @param id Application ID * @return Web response code */ @Path("stop/{id}") @@ -242,13 +251,16 @@ public Response stopApp(@PathParam("id") String id) { /** * Restart an application. * + *
{@code
    * @apiGroup AppDetailController
    * @apiName restartApp
    * @api {post} /app_details/restart/{id}  Restart one instance of application.
    * @apiParam {String} id Application ID to restart.
    * @apiSuccess {String} text Give deployment status
    * @apiError BadRequest Requested application does not restart.
-   * @param id - Application ID
+   * }
+ * + * @param id Application ID * @return Web response code */ @Path("restart/{id}") @@ -271,12 +283,15 @@ public Response restartApp(@PathParam("id") String id) { /** * Upgrade an application. * + *
{@code
    * @apiGroup AppDetailController
    * @apiName upgradeApp
    * @api {put} /app_details/upgrade/{id} Upgrade one instance of application.
    * @apiParam {String} id Application Name to upgrade.
    * @apiSuccess {String} text
    * @apiError BadRequest Requested application does not upgrade.
+   * }
+ * * @return Web response code */ @Path("upgrade/{id}") diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/controller/AppListController.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/controller/AppListController.java index d818f23cdcf615..473d305cb15e8e 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/controller/AppListController.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/controller/AppListController.java @@ -51,6 +51,7 @@ public AppListController() { /** * Get Application List. * + *
{@code
    * @apiGroup AppListController
    * @apiName get
    * @api {get} /app_list  Get list of deployed applications.
@@ -116,7 +117,9 @@ public AppListController() {
    *        ...
    *        }
    *     ]
-   * @return - Active application deployed by current user.
+   * }
+ * + * @return Active application deployed by current user. */ @GET @Produces(MediaType.APPLICATION_JSON) @@ -128,13 +131,16 @@ public List getList() { /** * Delete an application. * + *
{@code
    * @apiGroup AppListController
    * @apiName delete
    * @api {delete} /app_list  Delete one instance of application.
    * @apiParam {String} id Application name to delete.
    * @apiSuccess {String} text Delete request accepted
-   * @param id - application ID
-   * @param name - application name
+   * }
+ * + * @param id application ID + * @param name application name * @return Web response */ @DELETE @@ -152,13 +158,16 @@ public Response delete(@PathParam("id") String id, /** * Deploy an application. * + *
{@code
    * @apiGroup AppListController
    * @apiName deploy
    * @api {post} /app_list/{id}  Deploy one instance of application.
    * @apiParam {String} id Application ID to deploy.
    * @apiSuccess {String} text Give deployment status
    * @apiError BadRequest Unable to deploy requested application.
-   * @param id - application ID
+   * }
+ * + * @param id application ID * @return Web response */ @POST diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/controller/AppStoreController.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/controller/AppStoreController.java index 5abb548b5dc109..1dff3b2f54a99c 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/controller/AppStoreController.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-catalog/hadoop-yarn-applications-catalog-webapp/src/main/java/org/apache/hadoop/yarn/appcatalog/controller/AppStoreController.java @@ -49,6 +49,7 @@ public AppStoreController() { /** * Display the most frequently used applications on YARN AppCatalog home page. * + *
{@code
    * @apiGroup AppStoreController
    * @apiName get
    * @api {get} /app_store/recommended  Display recommended applications.
@@ -70,7 +71,9 @@ public AppStoreController() {
    *        ...
    *        }
    *     ]
-   * @return - List of YARN applications
+   * }
+ * + * @return List of YARN applications */ @GET @Path("recommended") @@ -83,6 +86,7 @@ public List get() { /** * Search for yarn applications from solr. * + *
{@code
    * @apiGroup AppStoreController
    * @apiName search
    * @api {get} /app_store/search  Find application from appstore.
@@ -105,8 +109,10 @@ public List get() {
    *        ...
    *        }
    *     ]
-   * @param keyword - search for keyword
-   * @return - List of YARN applications matching keyword search.
+   * }
+ * + * @param keyword search for keyword + * @return List of YARN applications matching keyword search. */ @GET @Path("search") @@ -133,6 +139,7 @@ public AppStoreEntry get(@PathParam("id") String id) { /** * Register an application. * + *
{@code
    * @apiGroup AppStoreController
    * @apiName register
    * @api {post} /app_store/register  Register an application in appstore.
@@ -171,7 +178,9 @@ public AppStoreEntry get(@PathParam("id") String id) {
    *     }
    * @apiSuccess {String} Response Application register result.
    * @apiError BadRequest Error in process application registration.
-   * @param app - Yarnfile in JSON form
+   * }
+ * + * @param app Yarnfile in JSON form * @return Web response */ @POST diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/api/records/Component.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/api/records/Component.java index 8a5b7d402f7738..1d66875d0a9041 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/api/records/Component.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/api/records/Component.java @@ -116,8 +116,6 @@ public class Component implements Serializable { * ON_FAILURE (Only restart component instance if instance exit code != * 0); * NEVER (Do not restart in any cases) - * - * @return restartPolicy **/ @XmlType(name = "restart_policy") @XmlEnum From 519a9264494665730f25460bc1e9944d1a117862 Mon Sep 17 00:00:00 2001 From: Akira Ajisaka Date: Tue, 20 Jan 2026 12:11:48 +0900 Subject: [PATCH 04/12] Update link to Java API docs --- hadoop-project/src/site/site.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hadoop-project/src/site/site.xml b/hadoop-project/src/site/site.xml index 6cc69a082679a8..33d4060cb1dc69 100644 --- a/hadoop-project/src/site/site.xml +++ b/hadoop-project/src/site/site.xml @@ -205,7 +205,7 @@ - + From d7bbac83796bb89b0de08ba02ee08b9b1c36b3df Mon Sep 17 00:00:00 2001 From: Akira Ajisaka Date: Wed, 21 Jan 2026 15:45:27 +0900 Subject: [PATCH 05/12] Additional javadoc error fix after rebasing --- .../hadoop/fs/azurebfs/utils/TracingHeaderVersion.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingHeaderVersion.java b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingHeaderVersion.java index c542e42827ca28..4ab66665f1be03 100644 --- a/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingHeaderVersion.java +++ b/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/utils/TracingHeaderVersion.java @@ -34,27 +34,36 @@ public enum TracingHeaderVersion { /** * Version 1 of the tracing header, which includes a version prefix and has 13 permanent fields. * This version is used for the current tracing header schema. + * + *
{@code
    * Schema: version:clientCorrelationId:clientRequestId:fileSystemId
    *         :primaryRequestId:streamId:opType:retryHeader:ingressHandler
    *         :position:operatedBlobCount:operationSpecificHeader:httpOperationHeader
+   * }
*/ V1("v1", 13), /** * Version 2 of the tracing header, which includes a version prefix and has 16 permanent fields. * This version is used for the current tracing header schema. + * + *
{@code
    * Schema: version:clientCorrelationId:clientRequestId:fileSystemId
    *         :primaryRequestId:streamId:opType:retryHeader:ingressHandler
    *         :position:operatedBlobCount:operationSpecificHeader:httpOperationHeader
    *         :resourceUtilizationMetrics:fnsEndptConvertedIndicator
+   * }
*/ V2("v2", 15), /** * Version 0 of the aggregated metrics tracing header, which includes * a version prefix and has 3 permanent fields. * This version is used for the aggregated metrics tracing header schema. + * + *
{@code
    * Schema: metricsVersion:List
    *      where AggregatedMetrics = clientCorrelationId:fileSystemId:aggregated-metrics
    *      and AggregatedMetrics is enclosed within [] and separated by :
+   * }
*/ AV0("av0", 3); From d5e55d54b5a92738de95007259f5a91e2f81101d Mon Sep 17 00:00:00 2001 From: Akira Ajisaka Date: Tue, 27 Jan 2026 11:13:03 +0900 Subject: [PATCH 06/12] Add HadoopDocEnvImpl class to avoid cast error --- .../hadoop-annotations/pom.xml | 7 ++ .../tools/HadoopDocEnvImpl.java | 95 +++++++++++++++++++ .../tools/RootDocProcessor.java | 3 +- pom.xml | 16 +++- 4 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/HadoopDocEnvImpl.java diff --git a/hadoop-common-project/hadoop-annotations/pom.xml b/hadoop-common-project/hadoop-annotations/pom.xml index 86bc5d9237922a..391202502ec5fc 100644 --- a/hadoop-common-project/hadoop-annotations/pom.xml +++ b/hadoop-common-project/hadoop-annotations/pom.xml @@ -37,6 +37,11 @@ + + + + + @@ -46,6 +51,8 @@ --add-modules jdk.javadoc + --add-exports + jdk.javadoc/jdk.javadoc.internal.tool=ALL-UNNAMED diff --git a/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/HadoopDocEnvImpl.java b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/HadoopDocEnvImpl.java new file mode 100644 index 00000000000000..223b6fc3327a07 --- /dev/null +++ b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/HadoopDocEnvImpl.java @@ -0,0 +1,95 @@ +package org.apache.hadoop.classification.tools; + +import com.sun.source.util.DocTrees; +import jdk.javadoc.doclet.DocletEnvironment; +import jdk.javadoc.internal.tool.DocEnvImpl; +import jdk.javadoc.internal.tool.ToolEnvironment; + +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import java.util.Set; + +/** + * This class extends Java internal DocEnvImpl to avoid cast error while + * migrating to JDK17. It delegates all invocations to the proxy. + * This class depends on JDK internal implementation, so we might need to + * update the source code when upgrading to upper JDK versions. + */ +public class HadoopDocEnvImpl extends DocEnvImpl { + + private final DocletEnvironment proxy; + + public HadoopDocEnvImpl(DocletEnvironment original, DocletEnvironment proxy) { + super(extractToolEnvironment(original), null); + this.proxy = proxy; + } + + // Use original ToolEnvironment to avoid NullPointerException + private static ToolEnvironment extractToolEnvironment(DocletEnvironment original) { + if (original instanceof DocEnvImpl) { + return ((DocEnvImpl) original).toolEnv; + } + throw new IllegalArgumentException( + "Expected DocEnvImpl but got: " + original.getClass().getName()); + } + + @Override + public Set getSpecifiedElements() { + return proxy.getSpecifiedElements(); + } + + @Override + public Set getIncludedElements() { + return proxy.getIncludedElements(); + } + + @Override + public DocTrees getDocTrees() { + return proxy.getDocTrees(); + } + + @Override + public Elements getElementUtils() { + return proxy.getElementUtils(); + } + + @Override + public Types getTypeUtils() { + return proxy.getTypeUtils(); + } + + @Override + public boolean isIncluded(Element e) { + return proxy.isIncluded(e); + } + + @Override + public boolean isSelected(Element e) { + return proxy.isSelected(e); + } + + @Override + public JavaFileManager getJavaFileManager() { + return proxy.getJavaFileManager(); + } + + @Override + public SourceVersion getSourceVersion() { + return proxy.getSourceVersion(); + } + + @Override + public DocletEnvironment.ModuleMode getModuleMode() { + return proxy.getModuleMode(); + } + + @Override + public JavaFileObject.Kind getFileKind(TypeElement type) { + return proxy.getFileKind(type); + } +} diff --git a/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/RootDocProcessor.java b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/RootDocProcessor.java index 741a1c7d068414..02bae178b4f4ff 100644 --- a/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/RootDocProcessor.java +++ b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/RootDocProcessor.java @@ -77,7 +77,8 @@ static boolean isTreatUnannotatedClassesAsPrivate() { } public static DocletEnvironment process(DocletEnvironment root) { - return (DocletEnvironment) wrap(root, DocletEnvironment.class); + DocletEnvironment wrapped = (DocletEnvironment) wrap(root, DocletEnvironment.class); + return new HadoopDocEnvImpl(root, wrapped); } private static final Map PROXIES = new WeakHashMap<>(); diff --git a/pom.xml b/pom.xml index bc39c4f4068ac1..3e625588b09d45 100644 --- a/pom.xml +++ b/pom.xml @@ -704,7 +704,21 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/x org.apache.hadoop.yarn* - + org.apache.hadoop.classification.tools.IncludePublicAnnotationsStandardDoclet + + + org.apache.hadoop + hadoop-annotations + ${project.version} + + + + -J--add-exports=jdk.javadoc/jdk.javadoc.internal.tool=ALL-UNNAMED + + + --add-exports + jdk.javadoc/jdk.javadoc.internal.tool=ALL-UNNAMED + false From 26535b3c2a6b4d277bbb86010f658cb1df4eeac3 Mon Sep 17 00:00:00 2001 From: Akira Ajisaka Date: Tue, 27 Jan 2026 14:58:38 +0900 Subject: [PATCH 07/12] Refactor code to reduce Java reflections --- .../tools/HadoopDocEnvImpl.java | 95 +++++- .../tools/RootDocProcessor.java | 320 +----------------- 2 files changed, 81 insertions(+), 334 deletions(-) diff --git a/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/HadoopDocEnvImpl.java b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/HadoopDocEnvImpl.java index 223b6fc3327a07..f88556b8bbf28c 100644 --- a/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/HadoopDocEnvImpl.java +++ b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/HadoopDocEnvImpl.java @@ -5,91 +5,152 @@ import jdk.javadoc.internal.tool.DocEnvImpl; import jdk.javadoc.internal.tool.ToolEnvironment; +import org.apache.hadoop.classification.InterfaceAudience; +import org.apache.hadoop.classification.InterfaceStability; + import javax.lang.model.SourceVersion; +import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; +import java.util.LinkedHashSet; import java.util.Set; +import java.util.stream.Collectors; /** * This class extends Java internal DocEnvImpl to avoid cast error while - * migrating to JDK17. It delegates all invocations to the proxy. + * migrating to JDK17. It filters elements based on Hadoop's InterfaceAudience + * and InterfaceStability annotations. * This class depends on JDK internal implementation, so we might need to * update the source code when upgrading to upper JDK versions. */ public class HadoopDocEnvImpl extends DocEnvImpl { - private final DocletEnvironment proxy; + private final DocletEnvironment delegate; + private final String stability; + private final boolean treatUnannotatedClassesAsPrivate; - public HadoopDocEnvImpl(DocletEnvironment original, DocletEnvironment proxy) { + public HadoopDocEnvImpl(DocletEnvironment original, String stability, + boolean treatUnannotatedClassesAsPrivate) { super(extractToolEnvironment(original), null); - this.proxy = proxy; + this.delegate = original; + this.stability = stability; + this.treatUnannotatedClassesAsPrivate = treatUnannotatedClassesAsPrivate; } // Use original ToolEnvironment to avoid NullPointerException private static ToolEnvironment extractToolEnvironment(DocletEnvironment original) { - if (original instanceof DocEnvImpl) { - return ((DocEnvImpl) original).toolEnv; + if (original instanceof DocEnvImpl impl) { + return impl.toolEnv; } throw new IllegalArgumentException( "Expected DocEnvImpl but got: " + original.getClass().getName()); } + private boolean exclude(Element el) { + boolean sawPublic = false; + + for (AnnotationMirror am : el.getAnnotationMirrors()) { + final String qname = am.getAnnotationType().toString(); + + if (qname.equals(InterfaceAudience.Private.class.getCanonicalName()) || qname.equals( + InterfaceAudience.LimitedPrivate.class.getCanonicalName())) { + return true; + } + + if (stability.equals(StabilityOptions.EVOLVING_OPTION)) { + if (qname.equals(InterfaceStability.Unstable.class.getCanonicalName())) { + return true; + } + } + if (stability.equals(StabilityOptions.STABLE_OPTION)) { + if (qname.equals(InterfaceStability.Unstable.class.getCanonicalName()) || qname.equals( + InterfaceStability.Evolving.class.getCanonicalName())) { + return true; + } + } + + if (qname.equals(InterfaceAudience.Public.class.getCanonicalName())) { + sawPublic = true; + } + } + + if (sawPublic) { + return false; + } + + if (treatUnannotatedClassesAsPrivate) { + ElementKind k = el.getKind(); + if (k == ElementKind.CLASS || k == ElementKind.INTERFACE + || k == ElementKind.ANNOTATION_TYPE) { + return true; + } + } + + return false; + } + @Override public Set getSpecifiedElements() { - return proxy.getSpecifiedElements(); + Set base = delegate.getSpecifiedElements(); + return base.stream().filter(e -> !exclude(e)) + .collect(Collectors.toCollection(LinkedHashSet::new)); } @Override public Set getIncludedElements() { - return proxy.getIncludedElements(); + Set base = delegate.getIncludedElements(); + return base.stream().filter(e -> !exclude(e)) + .collect(Collectors.toCollection(LinkedHashSet::new)); } @Override public DocTrees getDocTrees() { - return proxy.getDocTrees(); + return delegate.getDocTrees(); } @Override public Elements getElementUtils() { - return proxy.getElementUtils(); + return delegate.getElementUtils(); } @Override public Types getTypeUtils() { - return proxy.getTypeUtils(); + return delegate.getTypeUtils(); } @Override public boolean isIncluded(Element e) { - return proxy.isIncluded(e); + boolean base = delegate.isIncluded(e); + return base && !exclude(e); } @Override public boolean isSelected(Element e) { - return proxy.isSelected(e); + return delegate.isSelected(e); } @Override public JavaFileManager getJavaFileManager() { - return proxy.getJavaFileManager(); + return delegate.getJavaFileManager(); } @Override public SourceVersion getSourceVersion() { - return proxy.getSourceVersion(); + return delegate.getSourceVersion(); } @Override public DocletEnvironment.ModuleMode getModuleMode() { - return proxy.getModuleMode(); + return delegate.getModuleMode(); } @Override public JavaFileObject.Kind getFileKind(TypeElement type) { - return proxy.getFileKind(type); + return delegate.getFileKind(type); } } diff --git a/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/RootDocProcessor.java b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/RootDocProcessor.java index 02bae178b4f4ff..39d5fa25d07e62 100644 --- a/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/RootDocProcessor.java +++ b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/RootDocProcessor.java @@ -18,35 +18,10 @@ package org.apache.hadoop.classification.tools; import jdk.javadoc.doclet.DocletEnvironment; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.PackageElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; - -import java.lang.reflect.Array; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.WeakHashMap; -import java.util.stream.Collectors; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.classification.InterfaceStability; /** - * Process the {@link DocletEnvironment} by substituting with (nested) proxy objects that - * exclude elements with Private or LimitedPrivate annotations. + * Process the {@link DocletEnvironment} by filtering elements with + * Private or LimitedPrivate annotations using HadoopDocEnvImpl. *

* Based on code from http://www.sixlegs.com/blog/java/exclude-javadoc-tag.html. */ @@ -63,7 +38,6 @@ private RootDocProcessor() { // no instances } - static String getStability() { return stability; } @@ -77,294 +51,6 @@ static boolean isTreatUnannotatedClassesAsPrivate() { } public static DocletEnvironment process(DocletEnvironment root) { - DocletEnvironment wrapped = (DocletEnvironment) wrap(root, DocletEnvironment.class); - return new HadoopDocEnvImpl(root, wrapped); - } - - private static final Map PROXIES = new WeakHashMap<>(); - - private static Object wrap(Object obj, Class expectedType) { - if (obj == null) { - return null; - } - - if (obj instanceof DocletEnvironment) { - return getProxy(obj, new Class[]{DocletEnvironment.class}, - new EnvHandler((DocletEnvironment) obj)); - } - - if (obj instanceof Element) { - return getElementProxy((Element) obj); - } - - if (obj instanceof Set) { - return filterAndWrapIterable((Iterable) obj, true); - } - if (obj instanceof Collection) { - return filterAndWrapIterable((Iterable) obj, false); - } - if (obj instanceof Iterable) { - return filterAndWrapIterable((Iterable) obj, false); - } - - if (obj.getClass().isArray()) { - int len = Array.getLength(obj); - Object[] res = new Object[len]; - for (int i = 0; i < len; i++) { - Object v = Array.get(obj, i); - res[i] = wrap(v, v != null ? v.getClass() : Object.class); - } - return res; - } - - return obj; - } - - private static Object getElementProxy(Element el) { - Object cached = PROXIES.get(el); - if (cached != null) { - return cached; - } - - Set> ifaces = new LinkedHashSet<>(); - Collections.addAll(ifaces, el.getClass().getInterfaces()); - ifaces.add(Element.class); - if (el instanceof TypeElement) { - ifaces.add(TypeElement.class); - } - if (el instanceof PackageElement) { - ifaces.add(PackageElement.class); - } - if (el instanceof ExecutableElement) { - ifaces.add(ExecutableElement.class); - } - if (el instanceof VariableElement) { - ifaces.add(VariableElement.class); - } - - Object proxy = getProxy(el, ifaces.toArray(new Class[0]), new ElementHandler(el)); - PROXIES.put(el, proxy); - return proxy; - } - - private static Object getProxy(Object target, Class[] ifaces, InvocationHandler h) { - Object cached = PROXIES.get(target); - if (cached != null) { - return cached; - } - Object p = Proxy.newProxyInstance(target.getClass().getClassLoader(), ifaces, h); - PROXIES.put(target, p); - return p; - } - - @SuppressWarnings("unchecked") - private static Object filterAndWrapIterable(Iterable iterable, boolean preserveSet) { - if (iterable == null) { - return null; - } - if (preserveSet) { - Set out = new LinkedHashSet<>(); - for (Object o : iterable) { - if (o instanceof Element) { - Element el = (Element) o; - if (!exclude(el)) { - out.add(getElementProxy(el)); - } - } else { - out.add(wrap(o, o != null ? o.getClass() : Object.class)); - } - } - return out; - } else { - List out = new ArrayList<>(); - for (Object o : iterable) { - if (o instanceof Element) { - Element el = (Element) o; - if (!exclude(el)) { - out.add(getElementProxy(el)); - } - } else { - out.add(wrap(o, o != null ? o.getClass() : Object.class)); - } - } - return out; - } - } - - private static Object unwrap(Object maybeProxy) { - if (!(maybeProxy instanceof Proxy)) { - return maybeProxy; - } - InvocationHandler ih = Proxy.getInvocationHandler(maybeProxy); - if (ih instanceof BaseHandler) { - return ((BaseHandler) ih).target; - } - return maybeProxy; - } - - private static boolean exclude(Element el) { - boolean sawPublic = false; - - for (AnnotationMirror am : el.getAnnotationMirrors()) { - final String qname = am.getAnnotationType().toString(); - - if (qname.equals(InterfaceAudience.Private.class.getCanonicalName()) - || qname.equals(InterfaceAudience.LimitedPrivate.class.getCanonicalName())) { - return true; - } - - if (stability.equals(StabilityOptions.EVOLVING_OPTION)) { - if (qname.equals(InterfaceStability.Unstable.class.getCanonicalName())) { - return true; - } - } - if (stability.equals(StabilityOptions.STABLE_OPTION)) { - if (qname.equals(InterfaceStability.Unstable.class.getCanonicalName()) - || qname.equals(InterfaceStability.Evolving.class.getCanonicalName())) { - return true; - } - } - - if (qname.equals(InterfaceAudience.Public.class.getCanonicalName())) { - sawPublic = true; - } - } - - if (sawPublic) { - return false; - } - - if (isTreatUnannotatedClassesAsPrivate()) { - ElementKind k = el.getKind(); - if (k == ElementKind.CLASS || k == ElementKind.INTERFACE || - k == ElementKind.ANNOTATION_TYPE) { - return true; - } - } - - return false; - } - - private static abstract class BaseHandler implements InvocationHandler { - private final Object target; - - BaseHandler(Object target) { - this.target = target; - } - - protected Object getTarget() { - return target; - } - - Object wrapReturn(Object ret) { - if (ret == null) { - return null; - } - if (ret instanceof DocletEnvironment) { - return wrap(ret, DocletEnvironment.class); - } - if (ret instanceof Element) { - return getElementProxy((Element) ret); - } - if (ret instanceof Set) { - return filterAndWrapIterable((Set) ret, true); - } - if (ret instanceof Collection) { - return filterAndWrapIterable((Collection) ret, false); - } - if (ret instanceof Iterable) { - return filterAndWrapIterable((Iterable) ret, false); - } - if (ret.getClass().isArray()) { - return wrap(ret, ret.getClass()); - } - return ret; - } - - Object[] unwrapArgs(Object[] args) { - if (args == null) { - return null; - } - Object[] r = new Object[args.length]; - for (int i = 0; i < args.length; i++) { - r[i] = unwrap(args[i]); - } - return r; - } - } - - private static final class EnvHandler extends BaseHandler { - private final DocletEnvironment env; - - EnvHandler(DocletEnvironment env) { - super(env); - this.env = env; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - String name = method.getName(); - Object[] uargs = unwrapArgs(args); - - if ("getDocTrees".equals(name)) { - return env.getDocTrees(); - } else if ("isIncluded".equals(name)) { - Element e = (Element) uargs[0]; - boolean base = env.isIncluded(e); - return base && !exclude(e); - } else if ("getIncludedElements".equals(name)) { - Set base = env.getIncludedElements(); - return base.stream() - .filter(e -> !exclude(e)) - .collect(Collectors.toCollection(LinkedHashSet::new)); - } else if ("getSpecifiedElements".equals(name)) { - Set base = env.getSpecifiedElements(); - return base.stream() - .filter(e -> !exclude(e)) - .collect(Collectors.toCollection(LinkedHashSet::new)); - } - - Object ret = method.invoke(getTarget(), uargs); - return wrapReturn(ret); - } - } - - private static final class ElementHandler extends BaseHandler { - private final Element element; - - ElementHandler(Element element) { - super(element); - this.element = element; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - String name = method.getName(); - Object[] uargs = unwrapArgs(args); - - if ("equals".equals(name) && uargs != null && uargs.length == 1) { - return Objects.equals(element, unwrap(uargs[0])); - } - if ("hashCode".equals(name) && (uargs == null || uargs.length == 0)) { - return element.hashCode(); - } - if ("toString".equals(name) && (uargs == null || uargs.length == 0)) { - return element.toString(); - } - - if ("getEnclosedElements".equals(name) && (uargs == null || uargs.length == 0)) { - List enclosed = element.getEnclosedElements(); - List filtered = new ArrayList<>(); - for (Element e : enclosed) { - if (!exclude(e)) { - filtered.add(e); - } - } - return filtered; - } - - Object ret = method.invoke(getTarget(), uargs); - return wrapReturn(ret); - } + return new HadoopDocEnvImpl(root, stability, treatUnannotatedClassesAsPrivate); } } From 82309dff4530462894602f1e9b3e6cf113627e59 Mon Sep 17 00:00:00 2001 From: Akira Ajisaka Date: Tue, 27 Jan 2026 16:51:19 +0900 Subject: [PATCH 08/12] Add missing license header --- .../classification/tools/HadoopDocEnvImpl.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/HadoopDocEnvImpl.java b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/HadoopDocEnvImpl.java index f88556b8bbf28c..e580cef561274c 100644 --- a/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/HadoopDocEnvImpl.java +++ b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/HadoopDocEnvImpl.java @@ -1,3 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.apache.hadoop.classification.tools; import com.sun.source.util.DocTrees; From bfeaec44862f89cac25ef93a942feb2f611449cf Mon Sep 17 00:00:00 2001 From: Akira Ajisaka Date: Wed, 28 Jan 2026 11:05:37 +0900 Subject: [PATCH 09/12] Fix default stability level --- .../apache/hadoop/classification/tools/StabilityOptions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/StabilityOptions.java b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/StabilityOptions.java index c9d23ab472b724..a0b755cd0a0042 100644 --- a/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/StabilityOptions.java +++ b/hadoop-common-project/hadoop-annotations/src/main/java/org/apache/hadoop/classification/tools/StabilityOptions.java @@ -38,7 +38,7 @@ public final class StabilityOptions { public static final String UNSTABLE_OPTION = "-unstable"; enum Level { STABLE, EVOLVING, UNSTABLE } - private static volatile Level level = Level.STABLE; + private static volatile Level level = Level.UNSTABLE; static void setLevel(Level l) { if (l != null) { From 2ecadb29538b1e6265e94861d398dcc2bc1f8f0d Mon Sep 17 00:00:00 2001 From: Akira Ajisaka Date: Thu, 29 Jan 2026 14:18:33 +0900 Subject: [PATCH 10/12] Fix mvn javadoc:javadoc and checkstyle:checkstyle --- hadoop-common-project/hadoop-annotations/pom.xml | 5 ----- hadoop-project/pom.xml | 12 ++++++++++-- pom.xml | 6 ++++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/hadoop-common-project/hadoop-annotations/pom.xml b/hadoop-common-project/hadoop-annotations/pom.xml index 391202502ec5fc..e6d3c83c16bf7a 100644 --- a/hadoop-common-project/hadoop-annotations/pom.xml +++ b/hadoop-common-project/hadoop-annotations/pom.xml @@ -37,11 +37,6 @@ - - - - - diff --git a/hadoop-project/pom.xml b/hadoop-project/pom.xml index d902fd489edca4..e7f091031b5121 100644 --- a/hadoop-project/pom.xml +++ b/hadoop-project/pom.xml @@ -2316,8 +2316,15 @@ ${maven-javadoc-plugin.version} all + + + -J--add-exports=jdk.javadoc/jdk.javadoc.internal.tool=ALL-UNNAMED + - -Xmaxwarns 10000 + + --add-exports + jdk.javadoc/jdk.javadoc.internal.tool=ALL-UNNAMED + -Xmaxwarns 10000 @@ -2832,7 +2839,8 @@ 17 - ${javac.version} + ${javac.version} + ${javac.version} diff --git a/pom.xml b/pom.xml index 3e625588b09d45..791b6b0e622420 100644 --- a/pom.xml +++ b/pom.xml @@ -116,8 +116,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/x 4.4.1 2.5.0 1.0.0 - 3.1.0 - 8.29 + 3.6.0 + 11.1.0 7.1.1 4.9.7 4.9.7.0 @@ -713,9 +713,11 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/x + -J--add-exports=jdk.javadoc/jdk.javadoc.internal.tool=ALL-UNNAMED + --add-exports jdk.javadoc/jdk.javadoc.internal.tool=ALL-UNNAMED From 2c87dd5af7e68a2e6a14c9df35c0cb8254429495 Mon Sep 17 00:00:00 2001 From: Akira Ajisaka Date: Sat, 31 Jan 2026 18:33:27 +0900 Subject: [PATCH 11/12] Downgrade maven-javadoc-plugin < 3.10.0 to fix the output path --- hadoop-project/src/site/site.xml | 2 +- pom.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hadoop-project/src/site/site.xml b/hadoop-project/src/site/site.xml index 33d4060cb1dc69..6cc69a082679a8 100644 --- a/hadoop-project/src/site/site.xml +++ b/hadoop-project/src/site/site.xml @@ -205,7 +205,7 @@ - + diff --git a/pom.xml b/pom.xml index 791b6b0e622420..98499e53db8125 100644 --- a/pom.xml +++ b/pom.xml @@ -100,14 +100,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/x 2.8.1 - 3.21.0 + 3.9.1 1.5 1.7 2.4 3.8.1 3.5.0 2.0.0 - 3.12.0 + 3.8.0 1.5 1.5 3.0.1 From fa3894c327474f51259cb5158f2b802ca11f03b4 Mon Sep 17 00:00:00 2001 From: Akira Ajisaka Date: Sat, 31 Jan 2026 19:08:15 +0900 Subject: [PATCH 12/12] Remove jdk17+ profile and set --release flag in maven-compiler-plugin --- hadoop-common-project/hadoop-annotations/pom.xml | 6 +++++- hadoop-project/pom.xml | 11 ----------- pom.xml | 3 +++ 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/hadoop-common-project/hadoop-annotations/pom.xml b/hadoop-common-project/hadoop-annotations/pom.xml index e6d3c83c16bf7a..599ca9893cca75 100644 --- a/hadoop-common-project/hadoop-annotations/pom.xml +++ b/hadoop-common-project/hadoop-annotations/pom.xml @@ -42,7 +42,11 @@ org.apache.maven.plugins maven-compiler-plugin - + + + ${javac.version} + ${javac.version} --add-modules jdk.javadoc diff --git a/hadoop-project/pom.xml b/hadoop-project/pom.xml index e7f091031b5121..b9e2fe4b86439e 100644 --- a/hadoop-project/pom.xml +++ b/hadoop-project/pom.xml @@ -2832,17 +2832,6 @@ - - jdk17+ - - [17,) - - - 17 - ${javac.version} - ${javac.version} - - quiet-surefire diff --git a/pom.xml b/pom.xml index 98499e53db8125..1903969ac36a6e 100644 --- a/pom.xml +++ b/pom.xml @@ -548,6 +548,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/x org.apache.maven.plugins maven-compiler-plugin ${maven-compiler-plugin.version} + + ${javac.version} +