OpenAPITools / OpenAPITools/openapi-generator
[BUG] maven plugin generating java classes with non standard annotations
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 26.8k
- Forks
- 7.7k
- PR merge metrics
- PR metrics pending
Description
Description
The current Java classes generated by the plugin exhibit a few notable issues:
-
Non-standard annotations such as
@javax.annotation.Nonnullor@javax.annotation.Nullablefromcom.google.code.findbugs:jsr305:3.0.2are 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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the Java generator's POJO output for the provided OpenAPI declaration and compare the generated Request class with the expected example. Confirm that required fields use standard validation annotations and that those annotations are placed on fields, then rerun the two generation steps to verify the output.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- api
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100