I need to work with com.sun.tools.javac classes that are private and are not visible neither during compile nor run time.
I use:
JDK 11.0.15
Maven build tool
Intellij IDEA
My current state is that my imports are red-highlghited and compilation fails.
My class I want to use sun tools inside (sorry for the pic instead of code, my class is 2000+ lines length, for now I only care about availability of tools in my class):
pom.xml:
...
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
I need to be able to have these classes available as I "type", during mvn compile and in runtime.
com.sun packages I'd like to have:
com.sun.tools.javac.code
com.sun.tools.javac.comp
com.sun.tools.javac.file
com.sun.tools.javac.main
com.sun.tools.javac.model
com.sun.tools.javac.parser
com.sun.tools.javac.processing
com.sun.tools.javac.tree
com.sun.tools.javac.util
Thank you in advance!
I was able to make it work with the following compiler plugin configuration.
<compilerArgs>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg>
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg>
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED</arg>
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED</arg>
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED</arg>
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
</compilerArgs>
And other thing that broke my code was maven-javadoc-plugin added to my plugins.
The Javadoc for package com.sun.tools.javac in Java 11 says:
This package provides a legacy entry point for the javac tool. See the jdk.compiler module for details on replacement APIs.
👉 Access the module java.compiler, package javax.tools, for the interface JavaCompiler and class ToolProvider.
See the Javadoc for example code.
The com.sun package was never standard, never supported, and never intended for external use.
See JEP 403: Strongly Encapsulate JDK Internals.
Related
I had to integrate some legacy code into my maven build, so I used the maven-recommended toolchains plugin to change the java version:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-toolchains-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<goals>
<goal>toolchain</goal>
</goals>
</execution>
</executions>
<configuration>
<toolchains>
<jdk>
<version>1.5</version>
</jdk>
</toolchains>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.0</version>
<configuration>
<compilerArgs>
<arg>-Xmaxerrs</arg>
<arg>1000</arg>
</compilerArgs>
</configuration>
</plugin>
Then I ran into the max 100 compile errors problem which required passing special options to javac and found I was able to do it just with maven compiler:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.0</version>
<configuration>
<fork>true</fork>
<compilerVersion>1.5</compilerVersion>
<executable>C:\Java\jdk-1.5.0_22\bin\javac.exe</executable>
<source>1.5</source>
<target>1.5</target>
<compilerArgs>
<arg>-Xmaxerrs</arg>
<arg>1000</arg>
</compilerArgs>
</configuration>
</plugin>
Both snippets produce the same result: the java compiler is changed from the maven default to java 1.5. Both run in about the same amount of time, so there's no visible performance difference. I'd like to know if there are any benefits of one over the other so I know when to use each.
They do different things:
The compiler plugin specifically configures how your Java code is compiled (and only that).
The toolchains plugin just ensures that other plugins are all using the same Java tool chain (i.e. the same JDK) to compile, run, test, generate javadocs and so on.
This is explained in the respective plugins' documentation.
Note that not all plugins are "tool chain aware", but the compiler plugin is.
... are any benefits of one over the other
Well there there are things you can do with one and not the other and vice versa. For example, you can't set Java compiler options using the toolchain plugin.
However, they are not mutually exclusive. You can use both in the same POM file.
I am using the javadoc maven plugin and it creates the correct javadoc package, but all classes are created twice.
Maven dependency:
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.3.0</version>
</dependency>
My build code
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Can anyone help me please, what am I missing here?
command usage for doc generation
mvn clean install -Dresources="FirstProject/example_API"
I noticed the same problem and came upon a solution after enabling debug on the maven-javadoc-plugin maven plugin and seeing what it's doing. Specifically setting the sourcepath as shown below fixed the double listing problem for me and I've tried this on multiple version of Corretto 8 as well as Temurin 8. All had the double listing problem because it's an issue with the javadoc tool itself but setting the sourcepath manually fixed it for me.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.3.1</version>
<configuration>
<debug>true</debug>
<sourcepath>${basedir}/src/main/java</sourcepath>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
There's a bug in recent versions of the Maven Javadoc Plugin. The bug is known as MJAVADOC-700. It is dead easy to reproduce.
Downgrading to version 3.2.0 of the plugin fixes the problem. Setting the sourcepath explicitly is an alternative fix.
An existing maven pom project <packaging>pom</packaging> which currently collects and packages resources needs to be extended to validate some of the resources.
In the same project I created a java-source directory src/main/java and in there I created a small java class to validate some of the resources. In addition I configured the maven-compiler and exec-maven plugin in the pom.
The java class runs fine in the IDE but it fails when I do mvn clean install it fails because it cant find the compiled class file. This is because the compile/test-compile phase is not available for pom-packaged projects.
My questions are:
Can I modify the compiler plugin to execute (compile) in a different phase than the default compile-phase. (I tried with adding an execution tag but no success)
Why is the exec-maven plugin executed because this was defined in test phase, which according to the docs is not part of the pom-package.
Are there other possibilities to run this validation task in the pom?
Modifying the packaging from pom to jar is a political sub-optimal solution.
Yes, you can configure maven-compiler-plugin to run the compilation in the package phase of the pom packaging.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<mainClass>com.example.validate.App</mainClass>
</configuration>
</plugin>
</plugins>
</build>
As documented on this page, here is the maven-gpg-plugin block as used in the POM for all three of my projects:
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
How can you tell the version of this plugin that is actually installed on my computer? Is the fact that 1.5 seems to work good enough?
Thanks.
there could be multiple installed you are interested to know which one is being used effectively you need
mvn help:effective-pom
this will render effective pom.xml and you can figure out which version is effective
I have a maven module that I need to use in the J2ME client and in the EJB server. In the client I need to compile it for target 1.1 and in the server for target 1.6 .
I also need to deploy the 1.6 version to a Nexus repository, so the members working on the server project can include this dependency without needing to download the source code.
I've read at http://java.dzone.com/articles/maven-profile-best-practices that using profiles is not the best way of doing this, but the author didn't say what's the best way.
Here is my pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>proj-parent</artifactId>
<groupId>br.com.comp.proj</groupId>
<version>0.0.4-SNAPSHOT</version>
</parent>
<artifactId>proj-cryptolib</artifactId>
<name>proj - Cryto Lib</name>
<dependencies>
<dependency>
<groupId>br.com.comp</groupId>
<artifactId>comp-proj-mobile-messages</artifactId>
<version>0.0.2-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.3</source>
<target>1.1</target>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
</project>
As Haylem suggests thought you'll need to do it in two steps, one for the compile and one for the jars.
For the compiler
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<configuration>
<source>1.3</source>
<target>1.5</target>
<fork>true</fork>
<outputDirectory>${project.build.outputDirectory}_jdk5</outputDirectory>
</configuration>
</execution>
<execution>
<configuration>
<source>1.3</source>
<target>1.6</target>
<fork>true</fork>
<outputDirectory>${project.build.outputDirectory}_jdk6</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
And then for the jar plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classesDirectory>${project.build.outputDirectory}_jdk5</classesDirectory>
<classifier>jdk5</classifier>
</configuration>
</execution>
<execution>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classesDirectory>${project.build.outputDirectory}_jdk6</classesDirectory>
<classifier>jdk6</classifier>
</configuration>
</execution>
</executions>
</plugin>
you can then refer to the required jar by adding a <classifier> element to your dependency. e.g.
<dependency>
<groupId>br.com.comp.proj</groupId>
<artifactId>proj-cryptolib</artifactId>
<version>0.0.4-SNAPSHOT</version>
<classifier>jdk5</classifier>
</dependency>
You can configure this via the Maven compiler plugin.
Take a look at the Maven compiler plugin documentation.
You could enable this via different profiles for instance.
If you only want to have different target versions you could simply use a variable target. Something like this:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.3</source>
<target>${TARGET_VERSION}</target>
<fork>true</fork>
</configuration>
</plugin>
To complement my comment to wjans' answer, as you requested more details.
The following would have the compiler plugin executed twice to produce two different sets of classfiles, identified by what is called a classifier (basically, a marker for Maven to know what you refer to when a single project can produce multiple artifacts).
Roughly, something like:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<configuration>
<source>1.3</source>
<target>1.5</target>
<fork>true</fork>
<classifier>jdk5</classifier>
</configuration>
</execution>
<execution>
<configuration>
<source>1.3</source>
<target>1.6</target>
<fork>true</fork>
<classifier>jdk6</classifier>
</configuration>
</execution>
</executions>
</plugin>
Note that people sometimes frown on using classifiers, as they on using profiles, as they can possibly mean that your project should be scinded in multiple projects or that you are harming your build's portability.