Java 8 + Maven Javadoc plugin: Error fetching URL - java

I am attempting to generate Javadoc that actually links to the Javadoc for my dependencies. I have tried various means to generate Javadoc which does not produce the fully qualified class names for references to classes from my dependencies. I wanted links to the Java doc with the simplified class names. However, even with Java API classnames, I get NO links and have fully qualified class names. I am working with Java 8. I have the following configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.2</version>
<configuration>
<reportOutputDirectory>${project.basedir}/target</reportOutputDirectory>
<destDir>javadoc</destDir>
<windowtitle>Epiphany</windowtitle>
<doctitle>Epiphany</doctitle>
<show>private</show>
<detectLinks>false</detectLinks>
<detectOfflineLinks>true</detectOfflineLinks>
<linksource>true</linksource>
<detectJavaApiLink>false</detectJavaApiLink>
<additionalparam>-Xdoclint:none</additionalparam>
<links>
<link>http://docs.oracle.com/javase/8/docs/api</link>
</links>
</configuration>
<executions>
<execution>
<goals>
<goal>javadoc</goal>
<goal>test-javadoc</goal>
</goals>
</execution>
</executions>
</plugin>
I have the source set to Java 8 in my maven compiler configuration. I have tried using detectJavaApiLink set to true and leaving out the link to the Java 8 Javadoc, but Javadoc does not generate links to Java API classes and all references to them in my Javadoc are fully qualified class names.
I have tried setting detectJavaApiLink to false and using the above configuration with a specified URL(without and without a trailing slash) and I get the same result, along with this error:
[WARNING] javadoc: warning - Error fetching URL: http://docs.oracle.com/javase/8/docs/api
I have tried detecting links based on my declared dependencies, and I have tried setting it to false and then providing links to the Javadoc and I still get no links and all class names from classes in my dependencies are fully qualified. What the heck am I doing wrong? The package-list files are available at the URLs specified, so I don't get why Javadoc cannot access them or the Javadoc located there.
UPDATE:
Changed my version of the maven javadoc plugin to 2.10.3. Now, if I set detectJavaApiLink to true and remove the link for Java 8 javadoc, the javadoc generated properly links to Java API classes and used the simplified names.
However, I am still having problems with my 3rd party dependencies and linking to their Javadoc. If I set detectLinks to true, it fails to find the javadoc for any of them. If I set it to false and manually configure the location, I still get an error message saying it cannot fetch the URL:
[WARNING] javadoc: warning - Error fetching URL: https://selenium.googlecode.com/git/docs/api/java
My updated pom configuration for the maven javadoc plugin is below:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version>
<configuration>
<reportOutputDirectory>${project.basedir}/target</reportOutputDirectory>
<destDir>javadoc</destDir>
<windowtitle>Epiphany</windowtitle>
<doctitle>Epiphany</doctitle>
<show>private</show>
<detectLinks>false</detectLinks>
<detectOfflineLinks>true</detectOfflineLinks>
<linksource>true</linksource>
<additionalparam>-Xdoclint:none</additionalparam>
<detectJavaApiLink>true</detectJavaApiLink>
<links>
<link>https://selenium.googlecode.com/git/docs/api/java</link>
</links>
</configuration>
<executions>
<execution>
<goals>
<goal>javadoc</goal>
<goal>test-javadoc</goal>
</goals>
</execution>
</executions>
</plugin>
UPDATE 2:
Defect report filed with MJAVADOC:
https://issues.apache.org/jira/browse/MJAVADOC-427

Related

Migration from maven-jaxb2-plugin 0.14.0 to jaxb2-maven-plugin 2.5.0

Sharing my experience about migrating from
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.14.0</version>
to
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>2.5.0</version>
we have used the original plugin to generate sources out of WSDL files.
There was a request to use Java 11 instead of Java 8 and after the change the original plugin generated warnings.
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.sun.xml.bind.v2.runtime.reflect.opt.Injector (file:/D:/mr/org/glassfish/jaxb/jaxb-runtime/2.3.0/jaxb-runtime-2.3.0.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int)
WARNING: Please consider reporting this to the maintainers of com.sun.xml.bind.v2.runtime.reflect.opt.Injector
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Since this problem is still reported as a bug in maven-jaxb2-plugin and there was no update on this plugin since 2018, we have decided to move the mojo plugin.
Here is how the original execution looked like:
<execution>
<id>uniqa</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<schemaLanguage>WSDL</schemaLanguage>
<schemaDirectory>src/main/resources/brokeredinsurance/uniqa/out</schemaDirectory>
<schemaIncludes>
<include>*.wsdl</include>
</schemaIncludes>
<generatePackage>at.porschebank.brokeredinsurance.uniqa.out</generatePackage>
<generateDirectory>
${project.build.directory}/generated-sources/brokeredinsurance/uniqa/out
</generateDirectory>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics</artifactId>
<version>0.6.5</version>
</plugin>
</plugins>
<bindingDirectory>src/main/resources</bindingDirectory>
</configuration>
</execution>
and after migrating the new plugin
<execution>
<id>uniqa</id>
<goals>
<goal>xjc</goal>
</goals>
<configuration>
<sourceType>wsdl</sourceType>
<sources>
<source>src/main/resources/brokeredinsurance/uniqa/out</source>
</sources>
<packageName>at.porschebank.brokeredinsurance.uniqa.out</packageName>
<outputDirectory>
${project.build.directory}/generated-sources/brokeredinsurance/uniqa/out
</outputDirectory>
<xjbSources>
<xjbSource>src/main/resources/jaxb-bindings.xjb</xjbSource>
</xjbSources>
</configuration>
</execution>
In the new plugin we have different tags, but mapping them is quite obviously from the codes above.
I had to change the goal in the new execution since the new plugin uses different. So it went from generate to xjc. See the plugin documentation here What is the JAXB2 Maven Plugin? and about xjc here jaxb2:testXjc
We did not use anymore the <schemaInclude> tag because our directory contained only wsdl files.Also we removed the extra plugin definition, because it was not needed with the new plugin.
Summary
Moving to the new plugin was quite easy, but it needed a little time to figure it out the mapping of the tags.
However, I faced with one problem during the migration, because we have everything in the src/main/resources folder where we have the xjb file in the root.
The documentation says <xjbSource> can contain directories as well, what is valid, but when I defined only the folder I got the following error:
org.xml.sax.SAXParseException: not an external binding file. The root element must be {http://java.sun.com/xml/ns/jaxb}bindings but it is {http://schemas.xmlsoap.org/wsdl/}definitions
This is obvious, because we have the wsdl files in the same folder (in sub folders) as well and the plugin travers through the entire content during the initialization and it found first the wsdl file.
So, in my case, the solution was to define the path to the file. After this it generated the classes immediatelly.

maven-javadoc-plugin: How to update the module path dynamically

I have a Java (11.0.7) Maven (3.0.6) multi-module project that contains the following module declarations:
<modules>
<module>jdrum-commons</module>
<module>jdrum-datastore-base</module>
<module>jdrum-datastore-simple</module>
<module>jdrum</module>
</modules>
Each of these Maven modules contains a module-info that defines the necessary requirements and exports to restrict access and visibility.
As such, jdrum-datastore-simple has some test utility classes that I reuse in jdrum's tests. By configuring the surefire plugin in jdrum's config via the code snippet below I am able to package the whole project without any issues.
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>
<!-- Allow the unnamed module access to the tests at test-time -->
--add-opens jdrum/at.rovo.drum.impl=ALL-UNNAMED
--illegal-access=deny
</argLine>
</configuration>
</plugin>
</plugins>
</build>
Within the parents POM I've also configured the generation of a report via the site argument, which also generates the Javadoc of the respective projects. The configuration for the JAR containing the javadoc as well as the configuration for the Javadoc generation as part of the report are both the same and look like this:
<!-- Generate Javadoc while reporting -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<inherited>true</inherited>
<configuration>
<verbose>true</verbose>
<source>${maven.compiler.source}</source>
<show>protected</show>
<failOnWarnings>false</failOnWarnings>
<release>${maven.compiler.release}</release>
<stylesheet>java</stylesheet>
</configuration>
<reportSets>
<reportSet>
<id>html</id>
<reports>
<report>javadoc</report>
</reports>
</reportSet>
</reportSets>
</plugin>
The Javadoc generation as part of the package step, which generates the project-version-javadoc.jar as output, succeeds as both, the jdrum-datastore-simple dependencies as well as its tests, are only included at test time:
<!-- Test data store to use for testing -->
<dependency>
<groupId>at.rovo</groupId>
<artifactId>jdrum-datastore-simple</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>at.rovo</groupId>
<artifactId>jdrum-datastore-simple</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
<type>test-jar</type>
</dependency>
If I'd change the scope from test to compile or provided the Javadoc generation would also fail with an error such as
Exit code: 1 - javadoc: error - The code being documented uses packages in the unnamed module, but the packages defined in https://github.com/RovoMe/JDrum/jdrum-datastore-simple/apidocs/ are in named modules.
The issue here, as far as I understood the problem, is, that the jdrum-datastore-simple module is not added to the module path of Javadoc. The next logical step was therefore to add that module to the configuration as such:
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<additionalOptions>
<option>--add-modules</option>
<option>jdrum.datastore.simple</option>
</additionalOptions>
</configuration>
</plugin>
</plugins>
</reporting>
This adds the jdrum-datastore-simple module to the Javadoc configuration string, which can be seen in the jdrum/target/site/apidocs/options file that now contains an
...
--add-modules
jdrum.datastore.simple
...
entry. On further analyzing the generated options file it is apparent that the module path is missing out a reference to the actual JAR file and hence the Javadoc generation and thus the Maven process fails due to Javadoc not being able to locate the defined module. If I update that options file and add the path to the missing JAR file and then only perform a mvn package site the whole process succeeds and all is fine (as the pure invocation of the javadoc.bat located in the target/site/apidocs folder would as well).
Now, in order to make the whole process more dynamic I wanted to add or update the module path. However, the maven-javadoc-plugin does not directly allow this. Therefore I came up with adding a further maven-javadoc-plugin option of --module-path and a further option entry that contains the whole path. By the whole path I mean the path to every single dependency, so not only the path to jdrum-datastore-simple. This also works but due to hardcoding the path to the respective JAR files, the project is now not usable by other users unless they have the same system and path structure I used. To fix this I quickly replaced the respective path structure with ${settings.localRepository} and ${project.parent.basedir} properties on the respective modules in the module path. Unfortunately Javadoc is rather nitpicking on the path structure it accepts and it turns out that on my Windows machine Maven does return a path structure starting with C:\Users\... which Javadoc can't handle. If the path structure looks like C:/Users/... however Javadoc is fine with the values.
On further research I stumbled upon this thread which suggests to use Maven's build-helper-maven-plugin to define new properties for i.e. the M2 repository and use the built-in reg-ex capability to replace \ characters with /. However, adding a configuration such as
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>replace-local-repo-characters</id>
<goals>
<goal>regex-property</goal>
</goals>
<configuration>
<name>tag.m2repo</name>
<value>${settings.localRepository}</value>
<regex>\\</regex>
<replacement>/</replacement>
<failIfNoMatch>false</failIfNoMatch>
</configuration>
</execution>
<execution>
<id>replace-local-path-characters</id>
<goals>
<goal>regex-property</goal>
</goals>
<configuration>
<name>tag.basedir</name>
<value>${project.parent.basedir}</value>
<regex>\\</regex>
<replacement>/</replacement>
<failIfNoMatch>false</failIfNoMatch>
</configuration>
</execution>
</executions>
</plugin>
and using the introduced tags instead does not work at all as Maven is complaining about an invalid value provided. If I use $\{settings.localRepository} Maven is fine about the provided value, however in the final options file not the value of the actual settings.localRepository is updated but the provided string itself and I end up with something like $/{settings.localRepository}/org/slf4j/... which Javadoc can't resolve and therefore still misses out on the correct location to the jdrum-datastore-simple dependency.
So, how can I add the path to the missing dependency to maven-javadoc-plugin's module path defined in the generated options file so that the Maven is actually able to generate the whole report?
It seems that with java11 Update 9 (maybe also with update 8; not tested) maven-javadoc-plugin is able to correctly generate the Javadoc for multi-module projects without the need to alter the module-path.
For those interested how the actual Maven POM looks like:
Parent POM
POM for a shared module
POM for a sharing and consuming module
POM for the consuming module

Maven - check configured value and stop processing

I have a POM file which includes a property (under properties section) which has an IP value that we use when pushing it to git.
<device.ip>1.2.3.4</device.ip>
But for my builds, I need to use a another IP value, so I should change it to my required IP when I start to work on a new branch.
I'd like to be able to check the variable value at build startup and abort it given the variable value is different from what I need.
Any other solutions also welcomed.
(I hope my question would not be downgraded because of lack of code - there is no really code to write here. The scenario is quite self explanatory)
Than you for your advice.
You could use the maven-enforcer-plugin which support such checks.
The usage looks like this for the requirePropery rule.
<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M2</version>
<executions>
<execution>
<id>enforce-property</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireProperty>
<property>device.ip</property>
<message>You must set a device.ip property!</message>
<regex>.*\d.*</regex> <!-- Express the value you need. -->
<regexMessage>The device.ip property contain...</regexMessage>
</requireProperty>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
</project>
I would suggest splitting your project in modules.
Module 1 contains your code without any configuration.
Module 2 refers to module 1 and additionally contains what goes into production. For multiple deployments create an additional module for each. This is where your production property goes.
Module 3 refers to module 1 (but not 2) and contains whatever you need for development (configuration like this property and helper classes). For complex scenarios make an additional module for each.
This has worked well for me.

WAR bundles SNAPSHOT JARs with timestamps

I have this multi module project setup which uses Webstart and I need to bundle the WAR with SNAPSHOT JARs. When the JARs are bundled into the WAR, they are appended with a timestamp instead of the actual name. This is causing issues during their download.
Expected - ABC-1.0-SNAPSHOT.jar
Actual - ABC-1.0-20141002.211448-2.jar
Env:
OS: Unix
Maven: 3.2.1
JDK: 1.7
I have already tried useUniqueVersions=false by defining a maven-war-plugin and setting this in the manifest configuration.
My webstart config:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>webstart-maven-plugin</artifactId>
<version>1.0-beta-6</version>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>jnlp-download-servlet</goal>
</goals>
</execution>
</executions>
<configuration>
<outputDirectoryName>.</outputDirectoryName>
<excludeTransitive>true</excludeTransitive>
<commonJarResources>
<jarResource>
...
</jarResource>
</commonJarResources>
<jnlpFiles>
<jnlpFile>
<templateFilename>JNLP-INF/APPLICATION_TEMPLATE.JNLP</templateFilename>
<outputFilename>client.jnlp</outputFilename>
<jarResources>
<jarResource>
...
</jarResource>
</jarResources>
</jnlpFile>
</jnlpFiles>
<sign>
...
</sign>
<outputJarVersions>false</outputJarVersions>
</configuration>
Appreciate any inputs.
UPDATE
Adding details about the WAR plugin I added
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
</plugin>
The behavior continues. I read that maven 3 uses a unique snapshot system. But I am trying to work my way around it.
Also tried the following without any luck
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<outputFileNameMapping>${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension}</outputFileNameMapping>
</configuration>
</plugin>
The creators of the maven-webstart-plugin have accidentally inverted the meaning of the flag useUniqueVersions. When set to true it produces jars of the form -SNAPSHOT.jar and when set to false (the default) it produces jars of the form --.jar
I found that setting the useUniqueVersions flag to true in the maven pom configuration produced my desired results.
I needed it like this because when deployed with the datestamp version of the snapshots when trying to launch it I was getting a "Resource not found" error when it tried to get the snapshot jar it was trying to launch. Presumably this means that the servlet code itself is not set up to handle the different naming on disk, despite the fact that the specific datestamp version number does end up in the jnlp itself.

Managing JAXB-generated classes in a Maven project

I have a Maven-based project, in which I trying to add some JAXB classes automatically generated by the "jaxb2-maven-plugin" Maven plugin. However, my first cut has me in a circular dependency loop:
Because these JAXB classes aren't generated yet, my other sources which reference them have compilation errors.
Because those other sources have compilation errors, these JAXB classes don't get generated.
It seems like there are two obvious possibilities for solving this:
Comment-out the broken references, so that the project builds and the JAXB classes are automatically generated. Then copy those generated sources from /target into /src/main/java, so that references to them won't cause compilation errors.
Create an entirely separate project, consisting of nothing but the JAXB stuff. Include it as a dependency in my main project.
Am I missing something here? Option #1 seems flat-out ridiculous... that just can't be the manner in which people use JAXB. Option #2 seems more rational, but still rather inefficient and cumbersome. I really have to take on the overhead of an entirely separate project just to use JAXB?
Are there any more elegant approaches that developers use to reference JAXB-generated classes in the same project where the Maven plugin generates them?
UPDATE: By request, here is the relevant portion of my POM:
<build>
<plugins>
<plugin>
<!-- configure the compiler to compile to Java 1.6 -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- The name of your generated source package -->
<packageName>com.mypackage</packageName>
</configuration>
</plugin>
</plugins>
</build>
When I run mvn clean package, I DO see my JAXB sources being generated beneath the /target subdirectory. However, those generated sources are not being automatically added to the classpath for the compile phase.
POST-RESOLUTION UPDATE: It turns out that my compilation issues had more to do with the fact that I was running in Eclipse, and its Maven integration has some issues with "jaxb2-maven-plugin". See this StackOverflow question for more detail on that issue and its resolution.
How did you configure your jaxb maven plugin? Normally it runs in the generate-sources lifecycle, which comes before the compile lifecycle. So your JAXB generated classes should already be there when your own code gets compiled, Maven puts them in target/generated-source and puts that folder on the classpath.
Edit:
This is my code we use at work (and which works as expected):
<plugin>
<groupId>com.sun.tools.xjc.maven2</groupId>
<artifactId>maven-jaxb-plugin</artifactId>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaDirectory>src/main/resources/<companyname>/xsd</schemaDirectory>
<includeSchemas>
<includeSchema>retrieval.xsd</includeSchema>
<includeSchema>storage.xsd</includeSchema>
</includeSchemas>
</configuration>
</plugin>
Apparently we use yet another jaxb plugin... (see also this thread: Difference of Maven JAXB plugins).
i would suggest you to split jaxb-generated classes (api) and your BL classes (implementation) to 2 maven projects with separate pom.xml for each, and the main root pom.xml with the compilation order. that way, you will be able to build api.jar, then maven will install it inside the local repo, and after that you can use it as the dependency of your implementation. so it will looks like:
-API\
--pom.xml - for api, jaxb generation
-IMPL\
--pom.xml - for impl, api dependency is here
pom.xml - main pom.xml with references to the projects above
Maybe try using the maven-jaxb2-plugin instead:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.8.2</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
The answer from dfuse is correct, though. Either plugin should generate sources before compiling, and the result of the source generation will be on the classpath. I tested this with both plugins. Is it possible for you to post your schema, or at least the schema for the type that your code is failing to pick up on the classpath?

Categories