spring-boot-maven-plugin #ConditionalOnProperty - spring-boot

I am trying to use #ConditionalOnProperty while starting the application with the spring-boot-maven-plugin.
If I start the project with eclipse I just have to add -Dexample=true to the vm arguments.
#ConditionalOnProperty( name = "example", havingValue = "true", matchIfMissing = false )
I tried to do the same with the spring-boot-maven-plugin:
<jvmArguments>-Dexample=true</jvmArguments>
<jvmArguments>-Dspring-boot.run.arguments="--example=true"</jvmArguments>
<arguments>
<argument>-Dexample=true</argument>
<argument>-Dspring-boot.run.arguments="--example=true"</argument>
</arguments>
but none of these works.
If I add a profile
<jvmArguments>-Dspring.profiles.active=exampleProfile</jvmArguments>
which contains the argument example:true it works.
EDIT:
The exact argument is
<arguments>
<argument>openapi.offline=true</argument>
</arguments>
but the property is still not found
- #ConditionalOnProperty (openapi.offline=true) did not find property 'offline'
My conditional:
#ConditionalOnProperty( prefix = "openapi", name = "offline", havingValue = "true", matchIfMissing = false )
Solution:
I had multiple
<jvmArguments> -example1 </jvmArguments>
<jvmArguments> -example2 </jvmArguments>
but they override each other. So I had to put them all in one jvmarguments field
<jvmArguments> -example1 -example2 </jvmArguments>

you don't need the -D
Try this:
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>....</version>
<configuration>
<arguments>
<argument>--openapi.offline=true</argument>
</arguments>
</configuration>

Related

With the Maven Swagger code generation plugin, how can I generated DTOs from schemas with proper required annotations (e.g. #NotNull)?

I'm using the Maven swagger codegen plugin (v 3.0.17). I was curious how, if possible, would I configure the plugin so that when my DTOs are generated from my defined schemas, the required attributes are marked with "#NotNull" or "#NotEmpty" annotations. I have this defined in my inputSpec .yml
...
components:
...
schemas:
...
MyObjectDTO:
type: object
properties:
id:
type: integer
format: int32
readOnly: true
groupId:
type: integer
format: int64
required: true
...
required:
- groupId
description: my object
The generated DTO looks like
#Schema(description = "my object")
#Validated
#javax.annotation.Generated(value = "com.myco.codegen.SpringCodegen", date = "2022-07-22T15:18:11.693263100-05:00[America/Chicago]")
public class MyObjectDTO {
,,,
#JsonProperty("groupId")
private Integer groupId = null;
When this DTO is passed to a Spring REST controller which is #Validated, if the "groupId" field isn't populated, I would like validation to fail, and ultimately a 400 (bad request) error to be returned.
Maven plugin configuration is
<configuration>
<language>com.myco.myproject.mypackage.swagger.codegen.OAS3SpringCodegen
</language>
<apiPackage>com.myco.myproject.mypackage.api
</apiPackage>
<modelPackage>com.myco.mypackage.api.model
</modelPackage>
<languageSpecificPrimitives>true</languageSpecificPrimitives>
<generateApis>true</generateApis>
<generateApiTests>false</generateApiTests>
<generateModelTests>false</generateModelTests>
<generateApiDocumentation>true</generateApiDocumentation>
<generateModels>true</generateModels>
<generateSupportingFiles>false</generateSupportingFiles>
<importMappings>
<importMapping>LocalDateTime=OffsetDateTime</importMapping>
</importMappings>
<configOptions>
<throwsException>true</throwsException>
<interfaceOnly>true</interfaceOnly>
<java8>false</java8>
<dateLibrary>java8</dateLibrary>
<sourceFolder>.</sourceFolder>
<useTags>true</useTags>
</configOptions>
</configuration>
Try adding the org.springframework.boot:spring-boot-starter-validation
(or just javax.validation:validation-api / jakarta.validation:jakarta.validation-api) dependency to your project and enable useBeanValidation in the plugin configuration:
<configuration>
...
<configOptions>
...
<useBeanValidation>true</useBeanValidation>
</configOptions>
</configuration>
Also, try changing the language parameter to the standard <language>java</language> or <language>spring</language>.

OpenAPI Codegen "oneOf": Java classes not generated correctly

TLDR:
OpenAPI offers 'oneOf' property. The resulting java classes created do not seem to allow one of the possible instances.
Details:
I am creating the spring/java server side rest api code using OpenAPI maven plugin.
The request class is not such that the passed object is not parsed correctly. The following error is printed in the console.
JSON parse error: Could not resolve subtype of [simple type, class com.model.Issuer]: missing type id property 'type' (for POJO property 'issuer'); nested exception is com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve subtype of [simple type, class com.Issuer]: missing type id property 'type' (for POJO property 'issuer')\n at [Source: (PushbackInputStream); line: 3, column: 15] (through reference chain: com.IssueCredentialRequest[\"credential\"]->com.Credential[\"issuer\"])
The reason seem to be that the generated class does not have subtypes list in the annotation:
package com.sphereon.vdp.vc.service.model;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
#JsonSubTypes({
})
public interface OneOfIssuer {
}
There is another class which is generated correctly. The reason that this one is generated correctly is probably that this one deals with non-primitive types.
package com.sphereon.vdp.vc.service.model;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
#JsonSubTypes({
#JsonSubTypes.Type(value = VerifyPresentationRequest.class, name = "VerifyPresentationRequest"),
#JsonSubTypes.Type(value = ProoflessVerifyPresentationRequest.class, name = "ProoflessVerifyPresentationRequest")
})
public interface OneOfpresentationsVerifyBody {
}
Can someone point to how to fix the code generation for primitive types?
<plugin>
<groupId>io.swagger.codegen.v3</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>3.0.33</version>
<dependencies>
<dependency>
<groupId>com.github.jknack</groupId>
<artifactId>handlebars</artifactId>
<version>4.3.0</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>vc-rest-api-issuer-source-generation</id>
<goals>
<goal>generate</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<inputSpec>${pom.basedir}/specifications/issuer.yml</inputSpec>
<language>spring</language>
<apiPackage>com.company.vdp.vc.service.api</apiPackage>
<modelPackage>com.company.vdp.vc.service.model</modelPackage>
<artifactVersion>${project.version}</artifactVersion>
<generateModels>true</generateModels>
<generateApis>true</generateApis>
<generateModelDocumentation>true</generateModelDocumentation>
<generateSupportingFiles>true</generateSupportingFiles>
<verbose>${openapi-codegen-verbose}</verbose>
<output>${project.basedir}/target/generated-sources/java/api</output>
<ignoreFileOverride>${project.basedir}/target/generated-sources/java/api/.swagger-codegen-ignore</ignoreFileOverride>
<configOptions>
<delegatePattern>true</delegatePattern>
<dateLibrary>java8</dateLibrary>
<useTags>true</useTags>
</configOptions>
</configuration>
</execution>
<execution>
<id>vc-rest-api-verifier-source-generation</id>
<goals>
<goal>generate</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<inputSpec>${pom.basedir}/specifications/verifier.yml</inputSpec>
<language>spring</language>
<apiPackage>com.company.vdp.vc.service.api</apiPackage>
<modelPackage>com.company.vdp.vc.service.model</modelPackage>
<artifactVersion>${project.version}</artifactVersion>
<generateModels>true</generateModels>
<generateApis>true</generateApis>
<generateModelDocumentation>true</generateModelDocumentation>
<generateSupportingFiles>true</generateSupportingFiles>
<verbose>${openapi-codegen-verbose}</verbose>
<output>${project.basedir}/target/generated-sources/java/api</output>
<ignoreFileOverride>${project.basedir}/target/generated-sources/java/api/.swagger-codegen-ignore</ignoreFileOverride>
<configOptions>
<delegatePattern>true</delegatePattern>
<dateLibrary>java8</dateLibrary>
<useTags>true</useTags>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
Following is the spec file that I am using without editing.
https://github.com/w3c-ccg/vc-api/blob/main/components/Issuer.yml
https://github.com/w3c-ccg/vc-api/blob/main/verifier.yml

tests fat jar with maven shade-plugin

I need to build one jar for execution tests during CI process on server. This jar have to contains all test dependencies (like junit, mockito) and spring boot dependencies while my test will use spring. I wrote such maven configuration:
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<id>shade</id>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>${project.artifactId}-fat</finalName>
<minimizeJar>false</minimizeJar>
<shadeTestJar>false</shadeTestJar>
<artifactSet>
<includes>
<include>*:*</include>
</includes>
</artifactSet>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>pl.klolo.demo.demo.smoke.SmokeTestAppKt</mainClass>
<manifestEntries>
<Multi-Release>true</Multi-Release>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
Maven built one jar with all dependencies, but when I try to execute test I have strange error which I cannot understand:
2022-04-08 20:45:44.611 INFO 591618 --- [ main] p.k.d.demo.tests.DemoApplicationTests : No active profile set, falling back to 1 default profile: "default"
2022-04-08 20:45:45.018 ERROR 591618 --- [ main] o.s.boot.SpringApplication : Application run failed
java.lang.IllegalStateException: Unable to read meta-data for class
at org.springframework.boot.autoconfigure.AutoConfigurationSorter$AutoConfigurationClass.getAnnotationMetadata(AutoConfigurationSorter.java:237) ~[demo-fat.jar:0.0.1]
at org.springframework.boot.autoconfigure.AutoConfigurationSorter$AutoConfigurationClass.getOrder(AutoConfigurationSorter.java:208) ~[demo-fat.jar:0.0.1]
at org.springframework.boot.autoconfigure.AutoConfigurationSorter$AutoConfigurationClass.access$000(AutoConfigurationSorter.java:154) ~[demo-fat.jar:0.0.1]
at org.springframework.boot.autoconfigure.AutoConfigurationSorter.lambda$getInPriorityOrder$0(AutoConfigurationSorter.java:64) ~[demo-fat.jar:0.0.1]
at java.base/java.util.TimSort.countRunAndMakeAscending(TimSort.java:355) ~[na:na]
at java.base/java.util.TimSort.sort(TimSort.java:220) ~[na:na]
at java.base/java.util.Arrays.sort(Arrays.java:1515) ~[na:na]
at java.base/java.util.ArrayList.sort(ArrayList.java:1750) ~[na:na]
at org.springframework.boot.autoconfigure.AutoConfigurationSorter.getInPriorityOrder(AutoConfigurationSorter.java:62) ~[demo-fat.jar:0.0.1]
Could you tell me what is wrong and how to fix it?
SmokeTestApp:
fun main(args: Array<String>) {
val launcher = LauncherFactory.create()
val listener = SummaryGeneratingListener()
launcher.registerTestExecutionListeners(listener)
launcher.execute(
LauncherDiscoveryRequestBuilder.request()
.selectors(selectPackage("pl.klolo"))
.build()
)
printSummary(listener.summary)
exitProcess(
if (listener.summary.failures.isEmpty()) 0
else -1
)
}
fun printSummary(summary: TestExecutionSummary) {
println("Passed tests: ${summary.testsSucceededCount}")
summary.failures.forEach {
println("###FAILED TEST ${it.testIdentifier.uniqueId}###")
it.exception.printStackTrace()
}
}
DemoApplicationTests:
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
class DemoApplicationTests(
#Value("\${test.applicationURI}") val applicationURI: String,
#Value("\${test.applicationPort}") val applicationPort: Int
) {
init {
RestAssured.baseURI = applicationURI
RestAssured.port = applicationPort
}
#Tag("smoke_test")
#Test
fun contextLoads() {
println("smoke test ===> 1")
}
I found reason of my problem. It was file spring.factories with entry:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
When I removed file jar works correctly

Setting descriptions for mojos and parameters in maven plugin

I am writing a maven plugin and I would like to add some documentation for the available goals and parameters.
When I run mvn help:describe -Dplugin=myplugin -Ddetail it prints out available goals and parameters. However it lists (no description) everywhere. From searching the internet I could not figure out where such a description is to be set.
For reference, my plugin is written in scala and looks roughly like this.
import org.apache.maven.plugins.annotations.{ Component, Parameter }
class MyMojo extends AbstractMojo {
#Parameter(defaultValue = "false", readonly = false)
private var skipFormatting: Boolean = _
}
So my question would be: where can set a description, such that it will show up with mvn help:describe -Dplugin=myplugin?
I strongly recommend to use the following:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.6.0</version>
<executions>
<execution>
<id>default-descriptor</id>
<phase>process-classes</phase>
</execution>
<execution>
<id>generate-helpmojo</id>
<goals>
<goal>helpmojo</goal>
</goals>
</execution>
</executions>
</plugin>
which will generate the help part during the build process. And yes you have to add some javadoc like this:
#Mojo(name = "failure", defaultPhase = LifecyclePhase.NONE,
requiresDependencyResolution = ResolutionScope.NONE, threadSafe = true)
public class FailureMojo extends AbstractMojo {
I don't understand why you haven't have any annotations on your Mojo?
The documentation like this: https://maven.apache.org/plugins/maven-install-plugin/plugin-info.html will be generated from the javadoc on parameters etc. https://github.com/apache/maven-install-plugin/blob/master/src/main/java/org/apache/maven/plugins/install/InstallMojo.java#L69
Based on examples when running the help:describe on familiar plugins like the maven-jar-plugin, tt appears it's based on the Javadoc of the Mojo class.

Updating Apache Felix SCR to OSGi Declarative Services R6 - #Property

I'm updating from Apache Felix SCR Annotations to OSGi DS R6 ones and the one is causing me more problem is the #Property inside the class.
Before I had:
#Component (immediate = true)
#Service (A.class)
public class AImpl implements A
{
#Property (intValue = 604800)
public static final String A = "a";
...
}
Now I have:
#Component (service = A.class, immediate = true)
#Designate (ocd = Configuration.class)
public class AImpl implements A
{
...
}
and
#ObjectClassDefinition (name = "Bla")
public #interface Configuration
{
#AttributeDefinition (name = "A", type = AttributeType.INTEGER)
int A() default 604800;
}
The most bizarre thing on all of this is:
Before, I could see my AImpl class as a component.
Now, I couldn't see my AImpl class as a component and everyone who uses it cannot start because of unsatisfied references.
How come changing just configurations like this can cause this behaviour ? Maybe I'm missing something ?
The stranger part on all of this is my xml is inside the .jar and seems ok.
The scr:info is getting me nullpointer exception and I cannot see my component, meaning the scr:list will no help in anything.
XML BELLOW:
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.3.0" name="AImpl" immediate="true" activate="init" deactivate="stop">
<implementation class="AImpl"/>
<service>
<provide interface="A"/>
</service>
<reference name="Bla1" interface="Bla1Service" bind="bindBla1Service" unbind="unbindBla1Service"/>
<property name="PROP.EVENT.INTERVAL" type="Long" value="900000"/>
</scr:component>
Ps.: The classes are with strange names and so on because it's from a private company.
STACKTRACE:
2017-12-11T16:40:27.689+0100 [Framework Event Dispatcher] ERROR o.o.p.l.l.internal.FrameworkHandler:144 frameworkEvent FrameworkEvent ERROR - org.apache.felix.scr
org.osgi.framework.BundleException: The activator org.apache.felix.scr.impl.Activator for bundle org.apache.felix.scr is invalid
at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadBundleActivator(AbstractBundle.java:172)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:679)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:381)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.updateWorker(AbstractBundle.java:645)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.update(AbstractBundle.java:592)
at org.apache.felix.webconsole.internal.core.UpdateHelper.doRun(UpdateHelper.java:60)
at org.apache.felix.webconsole.internal.core.BaseUpdateInstallHelper.doRun(BaseUpdateInstallHelper.java:93)
at org.apache.felix.webconsole.internal.core.UpdateHelper.doRun(UpdateHelper.java:70)
at org.apache.felix.webconsole.internal.core.BaseUpdateInstallHelper.run(BaseUpdateInstallHelper.java:123)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassCastException: org.apache.felix.scr.impl.Activator cannot be cast to org.osgi.framework.BundleActivator
at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadBundleActivator(AbstractBundle.java:167)
... 9 common frames omitted
Part of POM.XML who install on karaf my bundles:
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-kar-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<inherited>false</inherited>
<configuration>
<includeScope>runtime</includeScope>
<prependGroupId>true</prependGroupId>
<excludeTransitive>true</excludeTransitive>
<artifactItems>
<artifactItem>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.framework</artifactId>
<version>${org.osgi.framework.version}</version>
</artifactItem>
<artifactItem>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>${org.osgi.core.version}</version>
</artifactItem>
<artifactItem>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr</artifactId>
<version>${org.apache.felix.scr.version}</version>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
This part looks like the error: service=AImpl.class. Your component should be published as a service using its interface A, not the implementation class.
This normally happens implicitly because the component directly implements interface A, but you have overridden that.
The solution should be to simply delete the service=AImpl.class attribute from the #Component annotation.
Your AImpl class still being a Component. However, now it's a "Configuration" Component, hence it has a #Designate annotation linking to a #ObjectClassDefinition Property class.
Go to the Configuration tab and you should see your Component and its properties.

Resources