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: