Kongchen Swagger is ignoring the #ApiModelProperty annotation - java

I've tried to add more information on my Swagger documentation, but I'm having some issues with the #ApiPropertyModel annotation in specific.
It doesn't matter what I try to do, it just doesn't work. The plugin is generating the Swagger.json correctly, all the #ApiOperation annotations are working for the REST resources, but for the model part, it only introspects the model classes' properties and doesn't look at the annotations above them.
Here is how the plugin is configured:
<plugin>
<groupId>com.github.kongchen</groupId>
<artifactId>swagger-maven-plugin</artifactId>
<version>3.1.5</version>
<configuration>
<apiSources>
<apiSource>
<locations>
<location>com.example.rest.resources</location>
<location>com.example.rest.model</location>
</locations>
<swaggerDirectory>${project.build.directory}/generated-sources</swaggerDirectory>
<basePath>/path/to/the/api</basePath>
<info>
<title>My RESTful API Documentation</title>
<version>${project.version}</version>
</info>
</apiSource>
</apiSources>
</configuration>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
If I have for example:
#ApiModelProperty(example = "test example")
public String test;
It will generate the test property but it won't create any example or any other property that I set up in that annotation. The same is happening when using it in a getter, so I think that's not the problem.
Am I doing anything wrong? Also, I looked at Kongchen's example project and I couldn't see anything special to make it work.

I was trying to mess with the code again, and I've found that the problem is on the structure of the project. It has different modules, and it has a profile for the general development and a profile just for the RESTful API documentation.
I was distracted for a while and started to build the projects using mvn clean package, and as it had a version of the project installed, it was using it to create the documentation, and that's why it was never changing, after I used mvn clean install in the main source code I could see the annotation make any effect.
I'm sorry guys, it was beyond any information I could give about the documentation project, since it was something about the whole structure I'm using. But at least I'll keep this answer so the next person may be aware about this.
Thank you for your attention!

Maybe you forgot the #ApiModel annotation on your Model classes?
Like:
#ApiModel
public class PostRequest {
#ApiModelProperty(example = "test example")
public String test;
}
or your model package does not match what's given in the pom.xml.

Related

Generate only REST interfaces for spring boot with openapi-generator-gradle-plugin

I tried to generate interfaces from a swagger file we need to implement. It's provided from an external source. I usually use contract first, but didn't do that in a long time with java/kotlin.
I already have a project set up and want to have as much control of my code as possible. I tried to use openapi-generator-gradle-plugin with kotlin-spring or spring generator, to generate the interfaces (the import part).
Best would be Interfaces with spring related annotations (RequestMappings etc.) and at least just the interfaces. But it seems, the generator also generates a "little application" (with gradle/maven file, SpringBootApp, README.md ...).
I don't have the code anymore, but was pretty sure, the last time I did this, it was easy possible to just generate interfaces, but can't remember which generator or plugin I used.
So my question is, did I miss something or is just creating interfaces not an issue anymore? Does everyone wants to do scaffolding here?
I use the openapi-generator-maven-plugin with <interfaceOnly>true</interfaceOnly> configOption. It should be similar in gradle with kotlin-spring generator
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>5.0.0-beta</version>
<executions>
<execution>
<id>1</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>openapi.json</inputSpec>
<generatorName>spring</generatorName>
<modelPackage>modelPackage</modelPackage>
<apiPackage>apiPackage</apiPackage>
<invokerPackage>invokerPackage</invokerPackage>
<configOptions>
<sourceFolder>target</sourceFolder>
<interfaceOnly>true</interfaceOnly>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
I added the following properties to my openApiGenerate task:
globalProperties =[
apis: '',
models: '',
]
which solved the issue for me.
If you are using gradle with a build.gradle.kts you can use this openapi-generator plugin task to generate the swagger code.
It does the same thing as the swagger codegen plugin:
plugins {
id("org.openapi.generator") version "5.1.1"
}
openApiGenerate {
generatorName.set("spring")
inputSpec.set("$rootDir/src/main/resources/petstore.yaml")
outputDir.set("$buildDir/generated/")
configFile.set("$rootDir/src/main/resources/api-config.json")
globalProperties.set(mapOf(
Pair("apis", ""), //no value or comma-separated api names
Pair("models", ""), //no value or comma-separated api names
))
}
The apis generated from the paths in your swagger. The api-config.json has the settings of your generator.
and then you need to add the generated classes to your sourceSet by doing:
configure<SourceSetContainer> {
named("main") {
java.srcDir("$buildDir/generated/src/main/java")
}
}
Finally make sure you generate the swagger files before compiling:
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
dependsOn("openApiGenerate")
kotlinOptions.jvmTarget = "11"
}

Querydsl - register custom types in pom.xml

I am trying to register my custom type in querydsl metadata exporter.
I have enum like this:
public enum RoleName {
ADMIN, USER;
}
Then, I created my custom type for querydsl:
public class RoleNameType extends EnumByNameType<RoleName> {
public RoleNameType(Class<RoleName> type) {
super(type);
}
}
My querydsl plugin setup in pom.xml:
<plugin>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-maven-plugin</artifactId>
<version>4.2.1</version>
<executions>
<execution>
<goals>
<goal>export</goal>
</goals>
</execution>
</executions>
<configuration>
<jdbcDriver>oracle.jdbc.driver.OracleDriver</jdbcDriver>
<jdbcUrl>jdbc:oracle:thin:#localhost:1521:xe</jdbcUrl>
<jdbcUser>user</jdbcUser>
<jdbcPassword>pass</jdbcPassword>
<packageName>com.example</packageName>
<targetFolder>target/generated-sources/java</targetFolder>
<namePrefix>BLANK</namePrefix>
<schemaPattern>TASK_MANAGER_USER</schemaPattern>
<customTypes>
<customType>com.example.RoleNameType</customType>
</customTypes>
<typeMappings>
<typeMapping>
<table>TM_ROLE</table>
<column>ROLE_NAME</column>
<type>com.example.RoleName</type>
</typeMapping>
</typeMappings>
<numericMappings>
<numericMapping>
<total>1</total>
<decimal>0</decimal>
<javaType>java.lang.Boolean</javaType>
</numericMapping>
</numericMappings>
</configuration>
<dependencies>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc14</artifactId>
<version>10.2.0.5</version>
</dependency>
</dependencies>
</plugin>
During building exception is returned:
"Caused by: java.lang.ClassNotFoundException: com.example.RoleNameType"
I already checked that there is no typo in package or class names.
Any ideas how to use querydsl metadata exporter together with my custom enum?
It's not really a solution to your problem, but maybe it helps to come to a faster conclusion for anyone else bumping into this issue:
I wanted to do the same thing which you've described and failed in the same way. After some time of trying and browsing the web I came across the querydsl Github project's issue #1865. #timowest's reply states that the project's sources are not part of the plugin's classpath. Hence, the exporter is not able to find the class specified in the type mapping which leads to the ClassNotFoundException.
He also stated that the project's dependencies are available in the classpath. I thought, I give it a try and extracted my enums putting them in a separate module within my project. The new module was added as a dependency to my original module. Unfortunately, the outcome was the same: A ClassNotFoundException was thrown, eventhough, the enum module appeared on the classpath checking Maven's debug output.
#timowest responded on that issue in 2016 and closed the issue as resolved. I didn't find any indication that it was actually resolved. So, I assume, there is no easy solution. The project seems to be inactive since one year, anyway.

using maven coordinate style episodes in wsimport

I'm building (multiple) complex webservice with base XSD types from all kinds of standards (GML, SWE, XLINK, etc). Now, I would like to break up the compilation into more steps, preferrably one for each of the standards I'm using.
Advantages:
1) I can add create tooling libraries that I can re-use in all of my webservices on each of the standards.
2) I can make use of the power of JAXB2 basics plugin, which seems to work very nicely with the maven-jaxb2-plugin (org.jvnet.jaxb2.maven2) and create for instance interface bindings. This in contrast with the jaxws-maven-plugin plugin.
The final step would be using the org.jvnet.jax-ws-commons:maven-jaxb2-plugin to create the actual web service that I can implement in an EJB (or call as a client).
Now, the org.jvnet.jaxb2.maven2:maven-jaxb2-plugin plugin allows me to refer to episodes by means of their maven coordinate, as part of its like this:
<episodes>
<episode>
<groupId>org.example</groupId>
<artifactId>jaxb2-basics-test-episodes-a</artifactId>
</episode>
</episodes>
How can I do this by means of the org.jvnet.jax-ws-commons:maven-jaxb2-plugin? I've searched a lot, and experimented like this:
<plugin>
<groupId>org.jvnet.jax-ws-commons</groupId>
<artifactId>>maven-jaxb2-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
</execution>
</executions>
<configuration>
<wsdlDirectory>src/main/resources/</wsdlDirectory>
<wsdlFiles>
<wsdlFile>example.wsdl</wsdlFile>
</wsdlFiles>
<xjcArgs>
<xjcArg>-b</xjcArg>
<xjcArg>../cpt-xsd/target/generated-sources/xjc/META-INF/sun-jaxb.episode</xjcArg>
</xjcArgs>
<verbose>true</verbose>
</configuration>
</plugin>
Which takes the episode file from the target dir of the (compiled) JAXB dependend project. This sometimes even fails in the maven build (why I did not figure out yet).
I've tried to use catalog files to make a mapping but (I think I saw somewhere a catalog mapping that took maven coordinates as destination), but haven't succeeded yet.
Are you aware of the OGC Schemas and Tools Project? (Disclaimer: I'm the author.)
Now, to your question. My guess would be that org.jvnet.jax-ws-commons:maven-jaxb2-plugin does not support the "Maven coordinates" as you call them. This was a feature I've specifically implemented for my org.jvnet.jaxb2.maven2:maven-jaxb2-plugin (disclaimer: I'm the author).
From the other hand, episode file is nothing but a JAXB binding file. So you can simply extract this file from the JAR artifact (for instance using the maven-dependency-plugin) and then include it more or less like you do it already. Just don't point to directories in other modules, this is not reliable.

Using aspects from other jars

What I'm trying to accomplish is the following:
I have a server with the following structure.
bin
apis
services
etc...
I want to define an API that contains an aspect to be used by services. Say:
#Aspect
public class AuthorizationAspect {
#Pointcut("call(* *()) && #annotation(Authorization)")
public void cutAuthorize() { }
#Before("cutAuthorize()")
public void callFromAuthorizeBefore() {
System.out.println("Test");
}
}
Then I define the service and annotate the methods I want with #Authorization and it gets pointcut by that aspect.
Things you should know:
Services only use the API to compile the code, therefore the scope is "provided", since the API will be already in the server.
Services JARs are loaded dynamically, so they will reside in another classloader.
My question is, how can I do this? How do I define my maven artifacts to accomplish that?
I noticed that the aspectj plugin has a weaveDependencies section, but this will also include in the service JAR all classes in that API (something that I want to avoid). Is this the right move?
Thanks in advance,
Rui
Take a look at how it's done in jcabi-aspects. You declare/compile your aspects in the API and then use this JAR as we com.jcabi:jcabi-aspects is being used in the example:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<configuration>
<aspectLibraries>
<aspectLibrary>
<groupId>com.jcabi</groupId>
<artifactId>jcabi-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
</plugin>
It's OK to have your aspects JAR in provided (or runtime) scope.

How do I use a template code generator (eg freemarker) in Maven?

How would you structure Freemarker (or an alternative) as a templating code generator into a Maven project? I'm pretty new to Maven and would appreciate some help.
I want to generate some code from templates in my project. [a]
Rather than write my own, googling found freemarker which appears to be used by Spring which is a good enough reference for me, though as I haven't started with it yet, any other suggestions that work well with Maven would be appreciated too.
This website tells me how to add it as a dependency to my pom.xml.
This SO question tells me where the generated sources should go. What I can't work out is how to tie it all together, so I get my generated sources generated from the templates, and then my generated sources used like regular sources for compile, test, jar, javadoc etc. Has anyone else used a template code generator for java within maven and could help?
[a] I know Generics would be the usual solution, and in fact I'm using them, but I have to use templates to cope with the primitive cases, without introducing copy/paste errors. Please trust me on this :-)
I had written a maven plugin for this purpose. It uses the FreeMarker Pre Processor.
Heres the fragment from pom.xml highlighting its usage:
<plugins>
<plugin>
<configuration>
<cfgFile>src/test/resources/freemarker/config.fmpp</cfgFile>
<outputDirectory>target/test/generated-sources/fmpp/</outputDirectory>
<templateDirectory>src/test/resources/fmpp/</templateDirectory>
</configuration>
<groupId>com.googlecode.fmpp-maven-plugin</groupId>
<artifactId>fmpp-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Here the cfgFile is the path where you keep the config file for FMPP. (if you are not using any special data passing in FreeMarker then an empty file will be enough)
templateDirectory is where you keep the FreeMarker templates.
outputDirectory is where you want the output files to be generated.
I am in process of writing a detailed documentation highlighting the plugins usage and will update the project website accordingly.
Here is another plugin for the job:
https://code.google.com/p/maven-replacer-plugin/
From the original description of the problem it sounds like you should consider creating a Maven Archetype (aka Project Template):
http://maven.apache.org/archetype/maven-archetype-plugin/
And it sounds like you might want to add some properties into the equation:
http://maven.apache.org/archetype/maven-archetype-plugin/examples/create-with-property-file.html
Maven Archetype functionality also provides a means of doing substitution using Apache Velocity (near enough the same as Freemarker) ... but I haven't worked that bit out yet.

Categories