I have an API written in Swagger for which I want to generate both the Service implementation and also the client, and they have to be in separate maven modules.
I was thinking of separating them into 3 separate Maven modules (or submodules of the same parent pom).
parent
+- api
+- src/main/resources/api/service.yaml
+- client
+- service
Then in both client and service I would have the swagger-codegen-maven-plugin. This way both will be in sync and I will only maintain the service from one place. Other clients can also depend on the api artifact and generate their code from the service.yaml Swagger API definition.
My difficulty is how do I make the service and client refer to the service.yaml in another Maven dependency?
This is what I currently have in the service pom.xml, but it refers to the local resources of the service module, not to the api maven dependency.
<plugin>
<groupId>io.swagger</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>${io.swagger.codegen.version}</version>
<executions>
<execution>
<id>api</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<!-- can this refer to another maven dependency's resources? -->
<inputSpec>${basedir}/src/main/resources/api/service.yaml</inputSpec>
<language>spring</language>
<library>spring-boot</library>
<modelPackage>com.test.model</modelPackage>
<apiPackage>com.test.api</apiPackage>
<generateSupportingFiles>false</generateSupportingFiles>
<configOptions>
<java8>true</java8>
<dateLibrary>java8</dateLibrary>
<interfaceOnly>true</interfaceOnly>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
Not sure if this is something I have to do from Maven, to refer to resources from another maven dependency, or something I have to do in the swagger plugin configuration.
The solution I managed to find is to use the maven-remote-resources-plugin. In the pom.xml of the maven project that needs to expose resources you can put:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-remote-resources-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>bundle</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>**/*.yaml</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
Then in the project that needs to import them, the project needs to be referred to as follows:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-remote-resources-plugin</artifactId>
<configuration>
<resourceBundles>
<resourceBundle>group:api:version</resourceBundle>
</resourceBundles>
</configuration>
<executions>
<execution>
<phase>
generate-sources
</phase>
<goals>
<goal>process</goal>
</goals>
</execution>
</executions>
</plugin>
where group:api:version is the group ID, artifact ID and version of the maven dependency exposing the resources.
Finally, inside the swagger-codegen-maven-plugin configuration, the yaml file can be referred to as:
<inputSpec>${project.build.directory}/maven-shared-archive-resources/api/service.yaml</inputSpec>
Related
I am looking to exclude the log4j in my pom file. It is not even available in the remote repository.
I have a property with version 4.0.0 in the parent pom file.
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>4.3.0</version>
<executions>
<execution>
<id>scala-compile-first</id>
<phase>process-resources</phase>
<goals>
<goal>add-source</goal>
<goal>compile</goal>
</goals>
<configuration>
<excludes>
<exclude>**/log4j*</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
It simply does not work; I keep getting the message below.
Execution scala-compile-first of goal net.alchim31.maven:scala-maven-plugin:4.3.0:add-source failed: Plugin net.alchim31.maven:scala-maven-plugin:4.3.0 or one of its dependencies could not be resolved: Failure to find org.apache.logging.log4j:log4j-core:jar:2.11.2
excludes configuration section inside the scala-maven-plugin is meant for filtering resources to be compiled.
In your case log4j is a dependency (already compiled), you have to find what is pulling it in the build and exclude it from there (or setup a global dependency exclusion rule).
I have created a multi-module project in maven which is as follows:
root/pom.xml
|________client/pom.xml
|________/src/main/java
|________/src/main/resources
|________common/pom.xml
|________/src/main/java
|________tools/pom.xml
|________/src/main/java
|________server/pom.xml
|________/src/main/java
|________/src/main/resources
I would like to compile the "client" module code which depends on ALL java classes in "common" module but on SOME java classes in the "tools" module.
Using the build-helper-maven-plugin as below, I was able to add all java source files under common/ path, but I need a way to define individual java files as sources which are under tools/.
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>../common/src/main/java</source>
<!-- Adding single java files as below does not work -->
<source>../tools/log/Log.java</source>
<source>../tools/socket/SocketClient.java</source>
<!----------------------------------------------------->
</sources>
</configuration>
</execution>
</executions>
You should include module "common" and "tools" as dependency in "client"
Then you can run build in the root of project: mvn clean install - it will build all modules.
Don't try to use parts of a module as dependency. Maven does not support this and it results in brittle and hard to maintain constructions.
If you only need parts of tools, then this is a clear signal that tools is too large and you need to split it up into two modules.
Ok, based on the comments received it seems that the ideal solution is to break the modules into sub-modules and use those as dependencies. However, as this is currently a time consuming task, I am posting a quick and dirty solution on how you can include one or more java files into your build by copying the files under a new source directory, src/main/external, and then add this directory as part of your sources.
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>copy-source-java-files</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>src/main/external</outputDirectory>
<overwrite>true</overwrite>
<resources>
<resource>
<!-- External source directory -->
<directory>../tools/src/main/java/</directory>
<includes>
<!-- Files to be copied along with their directory paths -->
<include>tools/log/Log.java</include>
<include>tools/socket/SocketClient.java</include>
<include>tools/client/reader/**</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/java</source>
<source>src/main/resources</source>
<source>../common/src/main/java</source>
<!-- Here we add the source with the files copied -->
<source>src/main/external</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
The output after compilation would be as follows:
root/pom.xml
|________client/pom.xml
|________/src/main/java
|________/src/main/resources
|________/src/main/external <----- This contains all external java files.
This feels like it should be easy, so please help point me in the correct direction.
I am successfully using maven to build my java project using a Azure Pipeline. I am also successfully getting JaCoCo coverage reports.
I have a maven project with multiple modules. Below is a sample project structure. I want to exclude everything in all the sub src/test/java directories/packages.
myproject
mod1
src/main/java/...
src/test/java/...
pom.xml
mod2
src/main/java/...
src/test/java/...
pom.xml
pom.xml
I would have expected something like setting codeCoverageClassFilter to -:*.src.test.java*.*, but none of my variations have worked. What is the correct statement to exclude all these test directories?
For excluded test add next configuration in pom parent
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.6</version>
<configuration>
<excludes>
<exclude>com/acme/test/*</exclude>
</excludes>
</configuration>
<executions>
<!-- prepare agent for measuring integration tests -->
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
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>
I have an artifact which is being built and deployed in a particular way (not as a jar file). In the course of deployment, a war file is built.
How can I configure the pom so that the artifact is also deployed as a jar file, to a different location?
Maven deploy means deploy artifact to a Maven Repository, not an application server.
Configure additional JAR artifact like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>make-a-jar</id>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
Attach this new artifact to your project:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>attach-artifacts</id>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>${project.build.directory}/${project.artifactId}-${project.version}.jar</file>
<!-- <file>${project.build.directory}/${project.build.finalName}.jar</file> - if finalName is defined -->
<type>jar</type>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
This blog post and its comments have the answer.
These three plugin configurations will allow you to build/install/deploy a jar version alongside the war.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>make-a-jar</id>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<packaging>jar</packaging>
<artifactId>${project.artifactId}</artifactId>
<groupId>${project.groupId}</groupId>
<version>${project.version}</version>
<file>
${project.build.directory}/${project.artifactId}-${project.version}.jar
</file>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<executions>
<execution>
<phase>deploy</phase>
<goals>
<goal>deploy-file</goal>
</goals>
<configuration>
<packaging>jar</packaging>
<generatePom>true</generatePom>
<url>${project.distributionManagement.repository.url}</url>
<artifactId>${project.artifactId}</artifactId>
<groupId>${project.groupId}</groupId>
<version>${project.version}</version>
<file>${project.build.directory}/${project.artifactId}-${project.version}.jar</file>
</configuration>
</execution>
</executions>
</plugin>
The "maven way" is to split out src/main/java into a separate module, and have the war file depend on that.
If you're absolutely resistant to that approach, you may be able to use a profile to alter the contents of the packaging element. I'm not sure if that's possible though.
Separating them is the right way to go. Forcing maven to produce a war and a jar in the same module is possible but will cause you problems down the road.
You should add the corresponding dependency of the artifact in the dependencies of the pom file.
Ex:
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-api</artifactId>
<version>1.2.2</version>
<scope>compile</scope>
</dependency>
One way to solve this is to have the module build a jar and then use the assembly plugin to build a war file with the jar in WEB-INF/lib of that war. I would strongly recommend against this. You'd be better off having a jar project and a war project with a parent project building both modules.