For the last few days, I have been trying to get the code for a REST-API client being generated into my project using the openapi-generator-maven-plugin. However, Maven fails in the compile-Phase as soon as it realizes that the third-party dependencies just introduced by the generated code have not been resolved yet. As the code generation itself works, my problem seems to be rather general and related to what's happening after code is being generated.
This is a sample POM, containing the copy-pasted contents of their own README on how to set the plugin up:
<?xml version="1.0" encoding="UTF-8"?>
<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>
<groupId>org.example</groupId>
<artifactId>openapi-generator-maven-plugin-error-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>5.0.0</version>
<!-- /RELEASE_VERSION -->
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v2.0/json/petstore.json</inputSpec>
<generatorName>java</generatorName>
<configOptions>
<sourceFolder>src/gen/java/main</sourceFolder>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Running mvn clean compile should generate the sources, and it does. However, as soon as the maven-compiler-plugin kicks in right after the code is being generated, it sees newly introduced package and symbol references in the generated code and consequently fails.
So I have tried to figure out how to install said dependencies, AFTER generation, but BEFORE compilation, but completely failed to do so. I suspect I need to use the maven-depndencies-plugin, but due to my limited knowledge of Maven and even more limited knowledge of how its plugins work, I am completely lost. I have tried adding the maven-dependency-plugin to my POM, but Maven completely ignores it and does not run it at all. I have tried to bind the resolve goal to the compile phase to no avail.
I would have expected code generation to not be a too uncommon thing to do with Maven, so I am a bit surprised it is actually so hard to pull off. Am I on the right tracks here? What exactly am I missing to have those transitive dependencies introduced in the generated code installed before the compiler is trying to compile them?
Related
Is there a way to configure the asciidoc-maven-plugin to include https-resources? I did some research and found the follwing (interesting) information, however, was not able to solve the problem according to the hints provided:
https://github.com/asciidoctor/asciidoctor/issues/1049
https://github.com/asciidoctor/asciidoctor-maven-plugin/issues/153
The latter link seemed to adress the exact problem I have, however, upgrading / changing versions did not have any effect.
The following pom.xml file is a minimum working example that allows you to replicate the problem:
<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>
<groupId>de.myproject</groupId>
<artifactId>my-project</artifactId>
<version>${revision}</version>
<packaging>pom</packaging>
<properties>
<revision>1.0.0-SNAPSHOT</revision>
<asciidoctor.maven.plugin.version>2.2.1</asciidoctor.maven.plugin.version>
<asciidoctorj.diagram.version>2.2.0</asciidoctorj.diagram.version>
<asciidoctorj.version>2.5.2</asciidoctorj.version>
<jruby.version>9.2.17.0</jruby.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>${asciidoctor.maven.plugin.version}</version>
<executions>
<execution>
<id>output-html5</id>
<phase>generate-resources</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<sourceDirectory>src/main/docs</sourceDirectory>
<outputDirectory>target/docs</outputDirectory>
<backend>html5</backend>
<doctype>book</doctype>
<attributes>
<safe-mode>UNSAFE</safe-mode>
<allow-uri-read>true</allow-uri-read>
</attributes>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
<version>${asciidoctorj.version}</version>
</dependency>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-complete</artifactId>
<version>${jruby.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
Now, if I save the following .adoc-file to the src/main/docs folder and run mvn clean install, I just get a notice Unresolved directive in my-project.adoc - include https://raw.githubusercontent.com/asciidoctor/asciidoctor/master/README.adoc instead of the actual document:
= my-project
include::https://raw.githubusercontent.com/asciidoctor/asciidoctor/master/README.adoc[]
However, if I donwload the above document (README.adoc) and reference it locally, I get the desired result. But this is not the way I want to include documentation by first downloading the file and then referencing it locally.
Does someone have an idea?
The idea is to only manage a single Maven project that contains all documentation including documentation from related projects that are also in our Gitlab repository. That is why I wanted to reference .adoc-files in those related projects by using include::https://concreteURLToAdocFile.
However, we realized, that it is a better idea to use the maven-dependency-plugin to first copy the .adoc-files from the other projects and then reference them locally.
This solution solved our concrete problem, however, it did not answer my original question.
I have a project that uses the MojoHaus Exec Maven plugin to run some Java code. Here's the pom.xml file:
<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>
<groupId>io.happycoding</groupId>
<artifactId>google-cloud-vision-hello-world-standalone</artifactId>
<version>1</version>
<properties>
<mainClass>io.happycoding.vision.CloudVisionHelloWorld</mainClass>
<exec.cleanupDaemonThreads>false</exec.cleanupDaemonThreads>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-vision</artifactId>
<version>1.100.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>${mainClass}</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
This works fine, and I can run my code using this command:
mvn clean package exec:java
I understand that the exec-maven-plugin plugin, which is specified in the plugins tag, runs the code using the mainClass property.
I was surprised to find that this pom.xml also works:
<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>
<groupId>io.happycoding</groupId>
<artifactId>google-cloud-vision-hello-world-standalone</artifactId>
<version>1</version>
<properties>
<exec.mainClass>io.happycoding.vision.CloudVisionHelloWorld</exec.mainClass>
<exec.cleanupDaemonThreads>false</exec.cleanupDaemonThreads>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-vision</artifactId>
<version>1.100.0</version>
</dependency>
</dependencies>
</project>
This file specifies the exec.mainClass property, but does not specify any plugins. However, I can still run my code just fine with this same command:
mvn clean package exec:java
But I don't understand how Maven knows to run this command without any plugins specified.
Is the Exec Maven plugin somehow automatically installed in Maven by default? Or is exec.mainClass somehow setting a property used by a different default tool within Maven?
I tried reading the official documentation, but I didn't see anything that mentions whether the plugin is included by default.
I've found that I can also pass the exec.mainClass property in as a command line argument, but I still don't understand how Maven knows what to do with that without the plugin being explicitly defined.
I much prefer the shorter file, but I want to make sure I understand how it's working and that I'm not missing anything that's going to bite me later.
When you specify exec:java, you are specifying a plugin, specifically exec-maven-plugin (along with the goal java). Other common plugins that are used by being explicitly identified on the command line rather than being attached to phases such as clean or package include versions, dependency, and archetype (this last of which doesn't even require a POM to be present, since it generally creates new ones).
Note that in your POM you don't attach exec to any phases (that plugin usually isn't); therefore your plugin entry serves only to provide configuration settings in the case you run the plugin explicitly from the command line, in your specific case equivalent to the exec.mainClass property.
I'm having some problems to make Sonar display code coverage for tests written in both Java and Groovy. I have a Maven multi-module project where a module can be exemplified like this:
firstServer
src/test/groovy
package1
GroovyTest1.groovy
GroovyTest2.groovy
src/test/java
package2
JavaTest1.java
JavaTest2.java
The pom.xml for firstServer looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
...
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.7.201606060606</version>
<configuration>
<destFile>${sonar.jacoco.reportPath}</destFile>
<append>true</append>
</configuration>
<executions>
<execution>
<id>agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
</build>
My Sonar properties are in the parent pom.xml:
<properties>
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPath>
</properties>
When I run the command mvn package sonar:sonar and visit SonarQube to see the results, the code coverage only takes java classes into account. I can't see any groovy classes among my unit tests even though I have many of them. I guess that I'm missing something in my POM files but I don't know what. I have read that it is possible to have a mix of Groovy and Java test classes when using Sonar and JaCoCo. My question is simply, what am I missing?
Thanks in advance!
You need to also add the sources and tests configuration:
<sonar.sources>src/main/java,src/main/groovy</sonar.sources>
<sonar.tests>src/test/java,src/test/groovy</sonar.tests>
It seems that the plugin ignores Groovy otherwise.
Install the Groovy plugin in Sonar. Login as admin/admin and go to the administration/system/update-center tab
Add the following property in the pom file
<sonar.tests>src/test/groovy,src/test/java</sonar.tests>
So I run maven package to build my dependencies into a jar. However, I need Maven to ignore any compilation errors and package the jar regardless.
How would this be accomplished? My pom.xml is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- Project specific stuff would be here... -->
<build>
<sourceDirectory>wherever</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<!-- etc... -->
</dependencies>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
Searching through SO only showed me how to ignore compilation errors from unit testing. I simply want my package to be compiled despite any errors in the code.
Edit: People seem to be bashing on me. I've been doing Java for 5 years. I know you're not supposed to compile with errors. I know what it entails.
My boss programs with me. He specifically said, "I can compile with errors in Eclipse, so compile with errors in Maven." It's not because I am ignorant, or because I refuse to accept my mistakes. It is because that is what I was specifically ordered to do. I did not ask this question because I am incompetent as many of you would like to assume.
Hate on me all you want, just know that you are doing so unfairly.
Use the exclude option to the compiler plugin to exclude the classes that have compile errors.
Building on Top of #wings Answer
You can use the flag failOnError=false in your pom, too
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<failOnError>false</failOnError>
</configuration>
</plugin>
or via command line
mvn package -Dmaven.compiler.failOnError=false
Maybe this is what you want:
https://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#failOnError
Set failOnError=false to ignore compilation errors.
When you run maven package. That means maven will run all phases before "package" phase. Hence maven compile will be triggered for sure. And because of compilation error, maven will stop at "compile" phase.
To package your project even with compilation error. I think you should use "maven assembly plugin" to package your depensencies ONLY and the phase of that plugin should be something before "compile". ex: "process-sources" or "process-resources".
By that way, before maven compiles your project's source code, you will have a bundle which includes all dependencies. Of course, maven will stop at the "compile" phase again. But you already have what you want.
Hope this help.
If it's just about the dependencies there's dependency:copy-dependencies:
Goal that copies the project dependencies from the repository to a defined location.
Use assembly:single with a user-defined descriptor to create the JAR with the dependencies from the location defined above:
Assemble an application bundle or distribution from an assembly descriptor.
I have a multi module project. The aspect is currently added to the "core" project. When doing a mvn clean install here it works. However trying to do a mvn clean install on parent project it fails with this error when compiling one of the other projects:
The type org.hibernate.annotations.CacheConcurrencyStrategy cannot be resolved. It is indirectly referenced from required .class files
If I add the Hibernate core dependency in that project too it works, but adding dependencies to projects that shouldn't have the dependency does not make sense - so it is not a solution. When compiling with javac it works fine.
What is the reason? And how can I fix it so I can use the AspectJ compiler without leaking dependencies to projects that shouldn't have that?
I have this configuration in the parent POM:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.5</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<complianceLevel>1.6</complianceLevel>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Update
I just found out. Running mvn clean install fails every time. However, running mvn [clean] install one time fails. Then running mvn install without clean works. I see that the builddef.lst in the target folder is the reason why it works and fails based on whether or not you run clean. So now my question is: How do you automatically generate this file?
Parent POM-file:
<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany</groupId>
<artifactId>core-lib</artifactId>
<name>core-lib</name>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.5</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<complianceLevel>1.6</complianceLevel>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.7.4</version>
</dependency>
</dependencies>
<modules>
<module>core-xyz</module>
<module>core-xyz2</module>
</modules>
</project>
Enable debug on the maven invocation to dig deeper. You should observe that the aspectj compile is only being invoked during the first maven invocation with the clean. Since the builddef.lst already exists after the first invocation, invoking without clean skips the aspectj compile.
This aspectj compile plugin behavior has been observed previously and was described here:
http://out-println.blogspot.com/2007/08/compile-time-checks-with-aspectj-part-2.html?m=1
You will need to look deeper to address the underlying issue, but as one commenter has already suggested, the aspectj compiler should only be enabled in modules that require it.
Otherwise, the additional dependencies are required for the aspectj compile, as you have already observed. I have incorporated aspectj compile into my own work without issue by restricting it to only the modules that require it.
According to the AspectJ compiler Maven plugin you could set up the argumentFileName to locate an existing builddef.lst.
So you can generate the builddef.lst and copy it to your resources folder, and instruct the AspectJ Maven plugin to use that file.