I am trying to use Swagger to document a Spring-MVC based REST-API and am having problems getting Swagger to reflect the use of custom serializers and deserializers.
Because the JSON must conform to an established format (which is not particularly well designed) and I wanted to have a properly designed API model in the Java classes, I have used a few custom implementations of JsonSerializer to generate the JSON output. When I enable Swagger with annotations in the Spring-MVC controllers, the generated documentation ignores the custom serializers and describes the model as if it had been serialized with the default Jackson settings. So far so good, I didn't really expect Swagger to automatically understand the implementation of the serializers.
What I however would expect (and I can't find anything about this in the Swagger documentation) is a way to use Swagger annotations on the relevant attributes in the model classes to manually describe the model. Am I missing something or is it really not possible to Swagger as a documentation tool in connection with custom serializers (or deserializers for that matter)?
Edit: The Swagger documentation is not particularly good, but I have already tried to work with #ApiModelProperty on the deviating properties. As far as I can see, it has absolutely no effect on the generated output (tested with Swagger-SpringMVC 0.8.5 and 0.9.5).
You can use model substitutes for e.g. Lets say you have a service
#RequestMapping(value = { "/some-resource" }, method = POST,
consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE)
#ResponseBody
public ResponseEntity<Void>
businessTypeEcho(#RequestBody CustomSerializableResource business) {
return new CustomSerializableResource();
}
you can setup a type substitution rule that tells springmvc how to represent the custom serializable type in the swagger ui.
#Bean //Don't forget the #Bean annotation
public SwaggerSpringMvcPlugin customImplementation(){
return new SwaggerSpringMvcPlugin(this.springSwaggerConfig)
.apiInfo(apiInfo())
.directModelSubstitute(CustomSerializableResource.class, SubstitutedSerializableResource.class)
.includePatterns(".*pet.*");
}
class SubstitutedSerializableResource {
//getters and setters that describe what
//CustomSerializableResource should look like in the UI
}
Unfortunately, this is going to create a parallel universe of types that aren't used at runtime.
Update:
If I understand your comment correctly, you're using it to format system-wide types i.e. booleans to Y/N or dates to mm/dd/yyyy perhaps. IMO, what you're probably looking for is to use model substitutes (see example above).
Substitute Date with String (this is the prescriptive guidance) In the case of dates your only option to communicate the format expected unfortunately is only via a textual description of the particular field or property.
Substitute Boolean with a enum you can create i.e. YesNoEnum that represents how you expect the objects to be serialized. This will provide the documentation with a set of allowed values.
At the end of the day, its a trade-off between creating these meta classes just for documentation vs. standardizing the API models to use serialization primitives as much as possible.
Related
Presently I am using swagger codegen tool to convert a RAML definition into swagger format and generating java client from this format. This gives me POJOs for all the data types mentioned in the RAML. Every time I change some data field in the RAML types, I have to regenerate the POJOs and all the code implementation in service layers has to be rewritten. It is becoming very cumbersome to repeatedly do the same things.
I am thinking if only these POJOs were generated with builder pattern, like,
mydataobject.builder.addfield1(10).addfield2(2);
it will greatly help me keep the code in service layer untouched.
Is there a way to auto-generate pojos that have builder methods in them?
You can use Lombok for that.
#lombok.Builder// Builder companion class, and static method
#lombok.Value // Getters, setters, and contructors
class Pojo {
String value;
Number number;
}
Which gives you this code:
final Pojo pojo = Pojo.builder()
.value("foo")
.number(100)
.build();
You have to proceed your generated code in order to add this annotations, see Add lombok (or any) annotation to swagger generated class for discussion of that.
I am working on a project that has a fair amount of data objects that use a "fluent interface" or "method chaining" on their setters so all of the setters in each data object return this. I have looked around and found this question, but it is unclear to me whether this can be used with Yaml as the annotations specifically mention JSON, and also this seems to enable mapping to objects using an actual builder pattern, which is a little different. The project is currently using SnakeYaml, but that can be tossed away if some other lib like Jackson can do this.
It turns out that this is in fact possible. Jackson supports yaml and will work with builder style setters by default without any extra configuration.
I need to make a DTO class that represents a JSON request body.
I’d like to make it fully immutable with final fields. I’ve already seen implementations based on #JSONCreator all args constructor but I also require one more feature.
The DTO class should be flexible and tolerate some missing fields in a request meanwhile ensure that all necessary properties are in-place.
Could you provide me an example of such DTO, please?
Jackson will automatically handle missing fields and just set those fields to null.
It also has some configuration options on whether when serializing responses, null fields should be omitted or set to the special value null.
objectMapper.setSerializationInclusion(Include.NON_NULL);
On another note, if you are designing an API, you might want to look at Swagger / OpenAPI and define your API declaratively from there (you can specify whether a field is optional or required). Then use the codegen tools to automaticlly generate your DTOs. (They will follow the best patterns and also offer Fluent API style setters).
As #jbx pointed out that Jackson automatically handles missing fields and sets it to null.
If you want to ensure that required fields are populated, you need to mark those as #javax.annotation.Nonnull or lombok.NonNull.
Using this Jackson throws a NullPointerException if that field in null while de-serialization of request to DTO class.
I am working on a CXF/JAXB code-first web service. I would like to be able to modify the WSDL definitions of some of the inputs.
For example, given the following interface snippet:
#WebMethod
public void Something(#WebParam(name="date") Date date);
The WSDL will generate the XMLSchema for the input "date" to be a "datetime" xml element. I would like it to be simply a "date" element instead.
It would also be nice to be able to specify the some of the other input attributes, such as minOccurs, etc.
For a custom object, the sub-elements can define all of these things through annotations such as XmlElement and XmlSchemaType. However, these annotations are not legal on an input parameter.
I know earlier versions of CXF did not handle this, but I'm not sure about the later versions. I'm currently running CXF 2.3.5.
Here is the answer I got from the cxf-users list:
1) Endorse the JAXB 2.2 API jar via one of the JDK endorsement mechanisms.
Then the XmlElement and XmlSchemaType annotations can be used on the parameter.
(This is not quite correct--the 2.2 jaxb that I endorsed did allow the #XmlElement annotation on a parameter, but it did not allow the #XmlSchemaType annotation)
2) Create the wrapper type beans (you can use java2ws -warpperBeans as a starting point) and add the #RequestWrapper/#ResponseWrapper annotations to
the method to point at them. You can finely control the appearance of the
wrapper schema via annotations in the beans.
3) You CAN configure extra subclasses of AbstractServiceConfiguration into the factories where you override some of the methods to set various
minOccurs/maxOccurs/etc.. type things. VERY fine level of control, but very
complex to do.
Are there any commonly usable annotations available? Similar to commons-lang?
If not, have you seen any effective use of annontations (not built-in annotations) as part of any open source application development.
I remember Mifos was using it for Transaction.
Mohan
i think Hibernate Validator has really good and reusable annotations for any kind of validation. it is based on a the reference implementation for JSR 303: Bean Validation.
Only non-standard annotations I've used more than once outside my testing project have been WicketStuff Annotations which are very useful in their own context.
Another interesting annotation set which is also the basis for JSR-305 is FindBugs' annotations which also may prove useful in the future - we'll see how that goes.
Check out my Bean annotations
http://code.google.com/p/javadude/wiki/Annotations
Things like
#Bean(
cloneable=true,
defineSimpleEqualsAndHashCode=true,
properties={
#Property(name="name", bound=true),
#Property(name="age", type=int.class, bound=true),
#Property(name="friend", type=Person.class, kind=PropertyKind.LIST)
},
observers={
#Observer(type=FeverListener.class)
}
)
public class Person extends PersonGen { }
The annotation processor generates the PersonGen superclass.
Note that I'm currently working on a major change to them and the API is changing (I'll still leave the current version available, but the 3.x.x version stream will be breaking)
I'm trying to get the new version done in the next couple of weeks.
JAXB defines annotations (javax.xml.bind.annotation) that are reused to some degree -- although they are named to indicate they only related to XML serialization, most of metadata has to do with annotating properties to serialize, so they can be used for serializing to other data formats (such as JSON) too. Jackson JSON processor supports them, along its own 'native' annotations, since there are no really standardizes non-data-format specific annotations (AFAIK).
I like and Oval http://oval.sourceforge.net/ and JAXB
there really needs to be a set of common annotationsin the core jre which are used in similar ways in multiple frameworks.
for example #Transactional #Nullable