openapi-generator
openapi-generator copied to clipboard
[BUG] maven plugin generating java classes with non standard annotations
Description
The current Java classes generated by the plugin exhibit a few notable issues:
-
Non-standard annotations such as
@javax.annotation.Nonnull
or@javax.annotation.Nullable
fromcom.google.code.findbugs:jsr305:3.0.2
are utilised. -
Annotations are placed at the method level instead of the recommended field level.
openapi-generator version
7.5.0
generatorName: java
OpenAPI declaration file content or url
{
"openapi": "3.1.0",
"info": {
"title": "Sample contract",
"version": "1.0.0"
},
"paths": {},
"components": {
"schemas": {
"Request": {
"type": "object",
"required": ["token"],
"properties": {
"token": {
"type": "string"
}
}
}
}
}
}
Generation Details
Generated java class
/*
* Sample contract
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
package com.sample;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.StringJoiner;
import java.util.Objects;
import java.util.Map;
import java.util.HashMap;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.Arrays;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
/**
* Request
*/
@JsonPropertyOrder({
Request.JSON_PROPERTY_TOKEN
})
@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2024-04-22T17:39:48.544568+02:00[Europe/Madrid]", comments = "Generator version: 7.5.0")
public class Request {
public static final String JSON_PROPERTY_TOKEN = "token";
private String token;
public Request() {
}
public Request token(String token) {
this.token = token;
return this;
}
/**
* Get token
* @return token
**/
@javax.annotation.Nonnull
@JsonProperty(JSON_PROPERTY_TOKEN)
@JsonInclude(value = JsonInclude.Include.ALWAYS)
public String getToken() {
return token;
}
@JsonProperty(JSON_PROPERTY_TOKEN)
@JsonInclude(value = JsonInclude.Include.ALWAYS)
public void setToken(String token) {
this.token = token;
}
/**
* Return true if this Request object is equal to o.
*/
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Request request = (Request) o;
return Objects.equals(this.token, request.token);
}
@Override
public int hashCode() {
return Objects.hash(token);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class Request {\n");
sb.append(" token: ").append(toIndentedString(token)).append("\n");
sb.append("}");
return sb.toString();
}
/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}
/**
* Convert the instance into URL query string.
*
* @return URL query string
*/
public String toUrlQueryString() {
return toUrlQueryString(null);
}
/**
* Convert the instance into URL query string.
*
* @param prefix prefix of the query string
* @return URL query string
*/
public String toUrlQueryString(String prefix) {
String suffix = "";
String containerSuffix = "";
String containerPrefix = "";
if (prefix == null) {
// style=form, explode=true, e.g. /pet?name=cat&type=manx
prefix = "";
} else {
// deepObject style e.g. /pet?id[name]=cat&id[type]=manx
prefix = prefix + "[";
suffix = "]";
containerSuffix = "]";
containerPrefix = "[";
}
StringJoiner joiner = new StringJoiner("&");
// add `token` to the URL query string
if (getToken() != null) {
joiner.add(String.format("%stoken%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getToken()), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
}
return joiner.toString();
}
}
Steps to reproduce
- Use OpenApi spec provided
- Generate java class (POJO)
Expected behaviour
To rectify these issues, the ideal Java class generation should adhere to the following specifications:
- Use standard annotations like
@javax.validation.constraints.NotNull
- Place annotations at the field level.
The expected behaviour can be summarised as follows:
package com.sample;
import javax.annotation.processing.Generated;
import javax.validation.constraints.NotNull;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
/**
* Request
* <p>
*
*
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"token"
})
public class Request {
/**
*
* (Required)
*
*/
@JsonProperty("token")
@NotNull
private String token;
/**
*
* (Required)
*
*/
@JsonProperty("token")
public String getToken() {
return token;
}
/**
*
* (Required)
*
*/
@JsonProperty("token")
public void setToken(String token) {
this.token = token;
}
public Request withToken(String token) {
this.token = token;
return this;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(Request.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('[');
sb.append("token");
sb.append('=');
sb.append(((this.token == null)?"<null>":this.token));
sb.append(',');
if (sb.charAt((sb.length()- 1)) == ',') {
sb.setCharAt((sb.length()- 1), ']');
} else {
sb.append(']');
}
return sb.toString();
}
@Override
public int hashCode() {
int result = 1;
result = ((result* 31)+((this.token == null)? 0 :this.token.hashCode()));
return result;
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if ((other instanceof Request) == false) {
return false;
}
Request rhs = ((Request) other);
return ((this.token == rhs.token)||((this.token!= null)&&this.token.equals(rhs.token)));
}
}
This revised code adheres to the standard annotations and correctly places them at the field level, as requested.