Use artifact version number in OpenAPI spec definition - maven

I have a maven project with my API definition using the OpenaAPI v3 specification.
I generate the code using the openapi-generator-maven-plugin and all works fine. I'm also able to access the swagger-ui and view and test my API.
The problem is that I don't want to maintain the version number twice. So I'd like to refer the version number from my maven pom in my api spec instead of duplicating it with the risk of it getting outdated.
I've tried maven resource filtering, which seems to work. Since the yaml file in the target folder gets it nicely replaced when I put ${project.version} in the version field in the spec, but when I open the swagger-ui it prints "${project.version}" literally instead of the actual version.
This is the plugin config from my pom:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>${openapi-generator-maven-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.build.resources[0].directory}/spec.yml</inputSpec>
<ignoreFileOverride>${project.build.resources[0].directory}/.openapi-codegen-ignore</ignoreFileOverride>
<language>spring</language>
<library>spring-boot</library>
<configOptions>
<!-- Use the newer java.time package instead of outdated java.util-->
<dateLibrary>java8</dateLibrary>
</configOptions>
<apiPackage>${default.package}.api</apiPackage>
<modelPackage>${default.package}.model</modelPackage>
<invokerPackage>${default.package}.invoker</invokerPackage>
<generateApiTests>false</generateApiTests>
</configuration>
</execution>
</executions>
</plugin>
...
</plugins>
</build>
This is my spec.yml:
openapi: 3.0.0
info:
version: ${project.version}
...

Thanks to the comment from #bcoughlan I was able to get the maven-resources-plugin working as desired.
Now it takes filters the *yml file from the src/main/resources folder and replaces the ${project.version} placeholder during the generates-sources phase. Because the openapi-generator-maven-plugin executes in the same phase and is defined later, it will be executed after the resource filtering and will operate on the api spec in the target folder as a result of ${project.build.outputDirectory}/spec.yml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>resources</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Codegen plugin for api. Depends on maven-resources-plugin to have executed in the generate-sources phase! -->
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>${openapi-generator-maven-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.build.outputDirectory}/spec.yml</inputSpec>
<ignoreFileOverride>${project.basedir}/.openapi-codegen-ignore</ignoreFileOverride>
<language>spring</language>
<library>spring-boot</library>
<configOptions>
<!-- Use the newer java.time package instead of outdated java.util-->
<dateLibrary>java8</dateLibrary>
</configOptions>
<apiPackage>${default.package}.api</apiPackage>
<modelPackage>${default.package}.model</modelPackage>
<invokerPackage>${default.package}.invoker</invokerPackage>
<generateApiTests>false</generateApiTests>
</configuration>
</execution>
</executions>
</plugin>
Note: the openapi-generator-maven-plugin is almost the same as the swagger-codegen-maven-plugin. More about the difference can be found here: https://openapi-generator.tech/docs/fork-qna
Note 2: When using spring-boot parent pom, you inherit resource.delimeter=# property and ${project.version} notation no longer works. So replacing the placeholder with #project.version# should fix that.

Related

Maven store MD5 checksum of file and file size in properties then filter another file

I am wondering if there is a way in Maven to calculate the MD5 checksum and size of a file, put them into properties then use those properties to filter (text replace) parameters in another file. I am trying to generate a config file for Advanced Installer before I run it.
After spending a while googling for ways to do it with Maven I decided to look into using the antrun plugin. I googled for both features and the first link of both solved the problem. Seems like antrun is a great way to script most things in Maven.
My antrun configuration:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<configuration>
<exportAntProperties>true</exportAntProperties>
</configuration>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<property name="my_path" value="some path"/>
<length file="${my_path}" property="file.size"/>
<checksum file="${my_path}" property="file.md5"/>
</target>
</configuration>
</execution>
</executions>
</plugin>
Maven resources plugin config:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<configuration>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>file1</include>
<include>file2</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>resources</goal>
</goals>
</execution>
</executions>
</plugin>
Which works great from the command line but for some reason the properties are not resolved in Intellij. I've posted another question for that.

maven-ejb-plugin: include generated sources

I have an EJB-maven-Project that has some generated classes (generated by JAXB).
They are generated into: target/generated-sources/jaxb/
Now, with maven-ejb-plugin I want them (i.e. their compilated classes) to be included into the client-jar, something like that:
<plugin>
<artifactId>maven-ejb-plugin</artifactId>
<version>2.3</version>
<configuration>
<!-- Tell Maven we are using EJB 3.1 -->
<ejbVersion>3.1</ejbVersion>
<generateClient>true</generateClient>
<clientIncludes>
<clientInclude>com/bla/ch/authorization/client/**</clientInclude>
<clientInclude>target/generated-sources/jaxb/**</clientInclude>
</clientIncludes>
</configuration>
</plugin>
This does not work, the generated classes are not part of the ejb-client-jar. (Though they are in the ejb-jar).
How can I do this correctly?
Include sources in your jar is probably not a good solution.
You may add generated sources in you resources locations, and then use source-plugin, to generate the so called artifact-sources.jar
<resources>
<resource>
<directory>${basedir}/target/generated-sources</directory>
<filtering>true</filtering>
</resource>
</resources>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
This is a better way than producing a jar with source code.

How to use <includes> / <excludes> in maven-remote-resources-plugin

I am trying to use the maven-remote-resources-plugin as per this example to selectively share common resources between multiple maven modules and I'm having a lot of difficulty getting the selective import of the resources to work.
I am trying to use <includes> and <excludes> elements as per below. I haven't seen these mentioned in doco for the plugin anywhere but eclipse provides them as valid options in the command completion and I don't get any errors when I run the pom. So far I haven't been able to get <includes> or <excludes> to have any effect at all on the imported resources
The relevant sections of my pom are;
Shared resources
<build>
<plugins>
<plugin>
<artifactId>maven-remote-resources-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>bundle</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>**/*</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
Resource consumer
<build>
...
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.3</version>
<configuration>
<resourceBunldes>
<resourceBundle>myApp:myApp_sharedresources:${project.version}</resourceBundle>
</resourceBundles>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
<includes>
<include>theOnlyResourceIWant.properties</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<phase>generate-resources</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>myApp</groupId>
<artifactId>myApp_sharedresources</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
I've tried many combinations of <includes> and <excludes> but all so far have had no impact.
So, are
<includes></includes>
and
<excludes></excludes>
valid elements for a maven-remote-resources-plugin configuration, and how do I use them?
I can reasonably seperate the resources out into seperate maven modules, but that could create a large number of single file maven modules and add a lot of extra xml so I'd like to avoid it if possible.
I'd really rather not start pawing through the plugin source code, but that is the next step.
I use a temp directory for the shared resources I'm importing and filter that.
Remote resource plugin configuration below. This copies all the shared resources into a temp directory in your project. Setting attached to false means they are not included in your final project artifact, which gives you the opportunity to select the ones you want to include using Maven's normal resource processing.
<plugin>
<artifactId>maven-remote-resources-plugin</artifactId>
<configuration>
<resourceBundles>
<resourceBundle>myApp:myApp_sharedresources:${project.version}</resourceBundle>
</resourceBundles>
<attached>false</attached>
<outputDirectory>${project.build.directory}/shared-resources</outputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<phase>generate-resources</phase>
</execution>
</executions>
</plugin>
Resource definition. When the maven-resource-plugin runs (it is bound to the lifecycle by default for jars/wars/ears), it will use the shared resource directory as well as the normal src/main/resources dir. You need to define both. (You may also enable resource filtering if you want.)
<resources>
<resource>
<directory>${project.build.directory}/shared-resources</directory>
<includes>
<include>theOnlyResourceIWant.properties</include>
</includes>
</resource>
<resource>
<directory>${basedir}/src/main/resources</directory>
</resource>
</resources>
I recommend making the shared directory be a subdirectory of ${project.build.directory}, so the clean lifecycle works without changes.
To enable the filter delimiters for the format '#{expr}' (Ruby-style), add the following to your plugin configuration:
<plugin>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>process-remote-resources</id>
<goals>
<goal>process</goal>
</goals>
<configuration>
<filterDelimiters>
<filterDelimiter>#{*}</filterDelimiter>
</filterDelimiters>
[...]
</configuration>
</execution>
</executions>
</plugin>
Check this link for reference

Maven: JspC should use external JSP-files

We're using Maven 3 and I'm facing a project that has JSP-files and also uses "global" JSP-files stored in a different project. This works nicely when using maven-war-plugin and webResources. All JSP-files find their way into the WAR-file.
The new idea is to pre-compile all the JSPs. The obvious choice is to use jspc-maven-plugin. However, that doesn't include the external JSPs when it compiles the project-local JSPs.
Here's the snippet from the pom.xml:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jspc-maven-plugin</artifactId>
<executions>
<execution>
<id>jspc</id>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1</version>
<configuration>
<warName>${pom.groupId}.${pom.artifactId}-0.0.1-SNAPSHOT</warName>
<webXml>${basedir}/target/jspweb.xml</webXml>
<webResources>
<resource>
<directory>../name.of.external.project/src/global/webapp</directory>
</resource>
</webResources>
</configuration>
</plugin>
The error is
[ERROR] Failed to execute goal org.codehaus.mojo:jspc-maven-plugin:1.4.6:compile (jspc) on project internal.project: JSPC Error: file:C:/workspace/name.of.internal.project/src/main/webapp/WEB-INF/views/show.jsp(2,0) File "/WEB-INF/views/../jspGlobal/jsp-declaration.jspf" not found -> [Help 1]
The jspGlobal-directory would get copied with the <directory>../name.of.external.project/src/global/webapp</directory>-line above.
What's missing to include the external JSPs in JspC?
EDIT: Thanks to prunge's and Raghuram's input I looked deeper into sources and JavaDocs. I noticed that the mentioned sources requires a FileSet which does NOT allow a list of directories. And since sources is also not a list, I see no chance how I can specify more than one JSP-source directory. I even tried to copy the <plugin>-element, but that didn't help. My current situation is this:
<plugin>
<groupId>org.codehaus.mojo.jspc</groupId>
<artifactId>jspc-maven-plugin</artifactId>
<version>2.0-alpha-3</version>
<executions>
<execution>
<id>jspc</id>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>
<directory>${basedir}/../name.of.external.project/src/global/webapp</directory>
</sources>
<!-- the later mentioned <sources> gets picked
<sources>
<directory>${basedir}/src/main/webapp</directory>
</sources>
-->
<!-- 1.6 doesn't work!? Something lower than 1.5 seems to be the default -->
<source>1.5</source>
<target>1.5</target>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.mojo.jspc</groupId>
<artifactId>jspc-compiler-tomcat6</artifactId>
<version>2.0-alpha-3</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1</version>
<configuration>
<warName>${pom.groupId}.${pom.artifactId}-0.0.1-SNAPSHOT</warName>
<webXml>${basedir}/target/jspweb.xml</webXml>
<webResources>
<resource>
<directory>../name.of.external.project/src/global/webapp</directory>
</resource>
</webResources>
</configuration>
</plugin>
Now the external JSPs are compiled into the target-path of the current project. Now I need a way to compile the JSPs of the current project. How do I do this?
BTW, if I switch the <sources> to the line for the current project I get the same error as mentioned earlier.
Perhaps you could try with the latest version of jspc-maven-plugin, which is 2.0-alpha-3. Do note that the usage is a little different from the earlier version.
Looking at the source code of CompilationMojoSupport, I see a sources property of type FileSet. You might be able to configure this in the configuration of the plugin to add additional source directories. It looks like by default it uses ${project.basedir}/src/main/webapp regardless of the configuration of the WAR plugin.

Maven: how to get a war package with resources copied in WEB-INF?

when I create a war package with maven, files and directories under the directory "src/main/resources" are copied in /WEB-INF/classes instead of /WEB-INF. How can I get them copied in /WEB-INF?
thanks,
rand
UPDATE:
in my pom now I use this:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>war</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>myapp/target/WEB-INF</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
and I launch mvn with:
mvn -Dmaven.test.skip=true clean package resources:copy-resources
but I got:
[INFO] One or more required plugin parameters are invalid/missing for 'resources:copy-resources'
[0] Inside the definition for plugin 'maven-resources-plugin' specify the following:
<configuration>
...
<outputDirectory>VALUE</outputDirectory>
</configuration>.
[1] Inside the definition for plugin 'maven-resources-plugin' specify the following:
<configuration>
...
<resources>VALUE</resources>
</configuration>.
I'm using maven 2.2 and the snippet basically is the same of the documentation
any idea?
either configure the outputDirectory parameter of resources:resources plugin, or put your files under src/main/webapp/WEB-INF/ directory.
resource plugin
EDIT:
This configuration is working for me:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.2</version>
<executions>
<execution>
<id>default-copy-resources</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<overwrite>true</overwrite>
<outputDirectory>${project.build.directory}/${project.artifactId}-${project.version}/WEB-INF/</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
you can run a phase in the form somePhase or a goal somePlugin:someGoal. The phase invocations will invoke all plugins goals hooked on phases in interval [validate,phase] in order, so there's no need to explicitly call them.
Web resources are not the same as java resources, which should be placed in the classpath. Web resources are processed via the war plugin and should be placed into src\main\webapp\WEB-INF\. In this case, it will work automatically without any additional configuration in the pom.xml
This configuration is working add plugin pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<webResources>
<!--copy resource file location-->
<resource>
<directory>${project.build.directory}/classes</directory>
</resource>
</webResources>
<!--location for add file-->
<webappDirectory>${project.build.directory}/${project.build.finalName}</webappDirectory>
</configuration>
</plugin>

Resources