简体   繁体   中英

How to generate SpringBoot models from Swagger yaml with Openapi Generator

we are using an API first approach and the API for our services is defined in swagger yamls. We then use Openapi generator to generate the interfaces that have to be implemented by the microservices. Also, the models are generated from the schemas.

This is where the question comes in. In one of the REST endpoints, I consume an XML let it be parsed by Spring-boot into a model and then save it to the database. At the moment I use a model that looks something like this:

@Data
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@Document("MyModel")
public class Model {

  @Id 
  @XmlTransient
  private String id;

  @XmlAttribute
  private String someAttribute;

  @XmlElement("childName")
  private List<OtherModel> children;

  @XmlElement("otherChildName")
  private List<OtherModel2> children2; 

}

With the other models being pretty similar. I like this because Spring-boot can use this to automatically parse the incoming XML and I can save this model directly to the database and return it as JSON.

The Models that are generated by Openapi Generator are missing the annotation, therefore, cannot be used to parse the XML and cannot be saved to the database. Are there any way in the yaml to tell it to add the @Id , @Document and some @Xml... annotations?

The main reason I'm trying to do this (use autogenerated models form swagger) is because this is a larger architecture where it would be nice if someone changes the API definition in the yaml, and for example adds fields the microservice(s) would also be build again and the models would be updated without manual updating java classes. Another way I thought about was generating the models the way Openapi does, then extending them with own classes and somehow add annotations afterward,... but I cannot think of any way how to do this so that you do not have to change the derived class if a field in the definition changes.

Example:

//class generated by openapigenerator
public class Model {
  private String field;
  private List<Submodel> children

  //autogenerated getters/setters
}

//model in my code
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@Document("MyModel")
public class MyModel extends Model {

  @Id 
  @XmlTransient
  @Getter
  @Setter
  private String id;

}

This would be ok but would be missing is the @Xml... annotations on some of the fields. I have seen that it generates @JsonProperty("somename") name just fine in case of json naming, but it seems using the XML: name/attribute properties in the yaml doesn't have any influence on the java code generated (or I'm doing something wrong, trying this: Documentation )

The only thing I could think of would be @Override -ing the getter/setters and annotating them with the attributes, but that would mean I have to touch every microservice that uses a derivate of the model defined by the API. I cannot move the derived class into the API project since the contexts (in this case XML/mongo) could vary much from microservice to microservice.

Any ideas on a good approach for this?

Cheers

----- EDIT ------

After digging in deeper I'm getting more sure that probably the right approach is to add the XML mappings ( @XmlAttribute / @XmlElement ) annotations in the swagger yaml the way it is mentioned in the documentation, and then extending it in the microservice code to add the database annotations. Basically like the second example only that in the base class the XML annotations would already be generated by swagger codegen. However I have not yet managed to make swagger codegen generate any XML annotation when building the schemas/models.

So first thing for openapi to generate XML annotations you need to have the withXml flag set to true in your configuration.

I went with the approach of using the XML specification in the openapi yaml file to generate a model with XML annotations that is used by Spring Boot to parse the incoming XML file.

Then I derived like in my second example another class and added the id and database annotations.

I believe this is a good approach for two reasons:

  1. If the openapi yaml is changed eg new fields are added to the XML or something similar, the code of the microservice does not have to be changed to reflect the new fields, only rebuild/redeployed.
  2. It reflects the differentiation of layers, the generated model reflects what is happening on the Http layer while the derived model reflects what is needed on the database layer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM