Swagger generating duplicated model classes - java

Generating server code for this minimal example using spring or jaxrs-spec creates 2 model classes: Pet.java and InlineResposne200.java. Except for the class name, they are identical.
The controller that responds to /pets returns a List<InlineResponse200> instead of List<Pet> and the class Pet is actually never used anywhere, even though the yaml definition uses $ref: "#/definitions/Pet". Why is this happening?
---
swagger: "2.0"
info:
version: "1.0.0"
title: "Swagger Petstore"
description: "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification"
termsOfService: "http://swagger.io/terms/"
contact:
name: "Swagger API Team"
license:
name: "MIT"
host: "petstore.swagger.io"
basePath: "/api"
schemes:
- "http"
consumes:
- "application/json"
produces:
- "application/json"
paths:
/pets:
get:
description: "Returns all pets from the system that the user has access to"
produces:
- "application/json"
responses:
"200":
description: "A list of pets."
schema:
type: "array"
items:
$ref: "#/definitions/Pet"
definitions:
Pet:
type: "object"
required:
- "id"
- "name"
properties:
id:
type: "integer"
format: "int64"
name:
type: "string"
tag:
type: "string"

I tried replicating this with swagger-codegen v2.2.2 using both spring and jaxrs-spec, but I was not able to get the InlineResponse200.java.
However, having done some more digging, I have found that this issue was recently reported as a bug. It has not yet been fixed, but the InlineResponse200.java isn't meant to be there.
This file seems to be incorrectly generated when using Swagger Editor v3. I'm guessing that's how you generated your file?
Whilst Swagger Editor v2 does not have this problem, my suggestion for the time being for you would be to install and use the latest stable version of swagger-codegen to generate your code from your Swagger.yaml file.
Hope this helps.

Related

How to access request type in RAML file (using webapi-parser)

Library used
webapi-parser 0.5.0
Language library used with
Java
Describe the issue
I am unable to find a method to access the type of request defined in the raml file
Input you have issues with
Below is the relavent section of RAML file
/testEndpoint:
type: rt.Item
post:
is: [t.ReturnsItemCreated, t.ExpectsContext, t.ReturnsNotFound, t.ReturnsBadGateway, t.ReturnsCommonErrors, t.NotCacheable]
body:
application/json:
type: bu.BlockCodeUpdatesRequestType
examples:
de-cards-bc: !include examples/example1.json
responses:
201:
body:
application/json:
type: bu.DeviceManagementResponseType
example: !include examples/ex2.json
Code you have issues with
After going through the documentation, I tried using operation.request().payloads().get(0).mediaType().value() but that returns application/json which isn't what I want, I want the type inside the application/json i.e. bu.BlockCodeUpdatesRequestType. Same is the case with the examples, I am unable to read those, the payloads().get(0).examples() comes up as empty for some reason and I don't know to access these. Getting just the path in the examples is enough.
Additional context
The variables like rt bu are RAML library files defined under uses:
I asked the same thing on Github here.

How to append to array in overridden YAML file (Spring)?

I have a JAR which contains an application.yml. That YAM file contains an array, e.g.:
things:
- name: one
color: red
I need to adjust this array at runtime by adding an additional application.yml file in the same directory as the JAR. However, I'm not sure how to append to the array, because the follow config seems to replace the config in the built-in YAML file in the JAR:
things:
- name: red
color: blue
In the end, during runtime, I need this:
things:
- name: one
color: red
- name: two
color: blue
There looks like a similar question was asked. Doesn't sound like it's supported. Looking through docs, I've found is some older docs show it's not supported.
When a collection is specified in multiple profiles, the one with highest priority is used (and only that one):
foo:
list:
- name: my name
description: my description
- name: another name
description: another description
---
spring:
profiles: dev
foo:
list:
- name: my another name
In the example above, considering that the dev profile is active, FooProperties.list will contain one MyPojo entry (with name “my another name” and description null).
A newer 2.6.0 snapshot doc mentions the same but seems to encourage you name your keys as their own objects. You might not have access to the beans bringing them in but it might be good to structure others in this way if you can.
Consider the following configuration:
my:
map:
key1:
name: "my name 1"
description: "my description 1"
---
spring:
config:
activate:
on-profile: "dev"
my:
map:
key1:
name: "dev name 1"
key2:
name: "dev name 2"
description: "dev description 2"
If the dev profile is not active, MyProperties.map contains one entry with key key1 (with a name of my name 1 and a description of my description 1). If the dev profile is enabled, however, map contains two entries with keys key1 (with a name of dev name 1 and a description of my description 1) and key2 (with a name of dev name 2 and a description of dev description 2).

Generate endpoints in separate classes with swager-codegen

I have below YAML for swagger-codegen and I want it to generate this endpoints in two separate classes, by default it generates one api class with both endpoints, is it s way to mark them as separate api?
/tenants:
post:
produces:
- application/json
consumes:
- application/json
parameters:
- name: body
in: body
required: true
schema:
$ref: "#/definitions/TenantRequest"
#################### User ####################
/tenants/{tenantId}/users:
post:
description: Create a User
produces:
- application/json
consumes:
- application/json
parameters:
- name: tenantId
in: path
required: true
type: string
- name: body
in: body
description: User object
required: true
schema:
$ref: "#/definitions/UserRequest"
If you want separate APIs to be created then you need to change /tenants: to /createTenants:
say for example you have 2 operations.
/user/add
/user/delete
If you try to generate API classes for the above operation then it will create class named UserApi with add and delete methods in it.
Now if you want separate API classes for add and delete then you need to change the end point as follows.
/addUser
/deleteUser

Swagger 1.5 not generating valid JSON description

I am trying to make swagger document my API composed of Jersey-spring 2.22.2 with Spring 4.3 and Jackson 2.22.2.
The swagger package I'm using is:
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<scope>compile</scope>
<version>1.5.12</version>
</dependency>
one of endpoint declaration:
#POST
#ApiOperation(
value = "creates folder hierarchy type client|lead",
notes = "creates folder hierarchy type client|lead"
)
#ApiResponses(value = {
#ApiResponse(code = 200, message = "creation successfull")
})
#Path("create_type")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response createHierarchy(
#ApiParam(value = "hierarchy type", required = true) #NotNull #FormDataParam("type") EHierarchyType hierarchyType,
#ApiParam(value = "parametric part of the hierarchy", required = true) #NotNull #FormDataParam("params") Map<String, Folder2> folderMap
) throws ItemExistsException, AccessDeniedException, PathNotFoundException, WebserviceException, RepositoryException, DatabaseException, ExtensionException, AutomationException, UnknowException, IOException, UserQuotaExceededException, LockException, VersionException {
StopWatch stopWatch = new StopWatch();
folderCtrl.createHierarchy(folderMap, hierarchyType);
logger.info("create hierarchy took: " + stopWatch.getElapsedTime());
return Response.ok().build();
}
and this is how the generated json looks like for this endpoint:
"/folder/create_type" : {
"post" : {
"tags" : [ "folder" ],
"summary" : "creates folder hierarchy type client|lead",
"description" : "creates folder hierarchy type client|lead",
"operationId" : "createHierarchy",
"consumes" : [ "multipart/form-data" ],
"parameters" : [ {
"name" : "type",
"in" : "formData",
"description" : "hierarchy type",
"required" : true,
"type" : "string",
"enum" : [ "CLIENT", "LEAD" ]
}, {
"name" : "params",
"in" : "formData",
"description" : "parametric part of the hierarchy",
"required" : true,
"type" : "object"
} ],
"responses" : {
"200" : {
"description" : "creation successfull"
}
}
}
}
when I try to parse this output in swagger editor it returns error back, and I think the reason might be that in "paramas" names parameter it has created its type of object instead of schema. My point here is to find out why? Is it some bug in swagger or it's me that missed something?
Also, on the another endpoint I have, there is #FormDataParam that is an pojo model object annotated with #ApiModel. This is translated by swagger as of type 'ref' but it doesn't gives user any other clue of what this object is or which fields it should contain. In Swagger-UI I see just 'undefined' as param type. This is not much informing. What I need to do in order to see the object's structure and to supply it's json definition as an example to try in ui?
Thanks
This answer contains examples of how the final Swagger spec should look like, but I don't know how to express that using Swagger #annotations. Hope this gives you some ideas anyway.
In Swagger 2.0, there is no straightforward way to have file + object in request body – form parameters can be primitive values, arrays and files but not objects, and body parameters support objects but not files (although you can try representing files as type: string – more on that below).
The next version, OpenAPI Specification 3.0 (which is RC at the time of writing) will support request body containing files + objects – check this example. I assume #annotations will be updated to support that too.
For now you have a couple of options.
1) One possible way is to pass the file contents as a binary string as part of the body parameter. Your API spec would look like:
paths:
/something:
post:
consumes:
- application/json
parameters:
- in: body
name: body
required: true
schema:
$ref: '#/definitions/FileWithMetadata'
...
definitions:
FileWithMetadata:
type: object
required: [file_data]
properties:
file_data:
type: string
format: binary # or format: byte
metadata:
type: object
additionalProperties:
type: string
2) Another possible way is to send the metadata names and values as separate arrays, so you would have 3 form parameters: file, array of key names, and array of key values. This is analog to:
curl -F "file=#foo.zip" -F "metadata_keys=description,author" -F "metadata_values=A ZIP file,Helen" https://api.example.com
Your API spec would look like this:
paths:
/something:
post:
consumes:
- multipart/form-data
parameters:
- in: formData
name: file
type: file
required: true
- in: formData
name: metadata_keys
type: array
items:
type: string
- in: formData
name: metadata_values
type: array
items:
type: string

Swagger Error Expected type string but found type integer

I started working recently on swagger to generate documentation for our RESTful apis. I use the yamlbeans-1.09.jar to convert my Java DTOs to a yaml file.
Everything works fine and the yaml is even validated properly on the http://www.yamllint.com/ but still while testing it with the Swagger interface, it gives an error "Expected type string but found type integer" and "No enum match for: 2" wherever I mention the swagger : 2.0 in the file.
My sample yml file is:
basePath: /employment
host: api.xxxx.com
schemes:
- https
swagger: 2.0
info:
title: API Doc
description: Description for the info goes here
version: 1.0.0
It always tends to give an error just a line number before the swagger version. Any help will be appreciated.
Edit: I have defined the swagger version as string in the java code and written as described below:
HashMap<String, Object> rootElementsForYml = new HashMap<String, Object>();
rootElementsForYml.put(SWAGGER, "2.0");
rootElementsForYml.put(HOST, "api.xxxx.com");
rootElementsForYml.put(BASEPATH, basePath);
rootElementsForYml.put(SCHEMES, new String[]{"https"});
But still it gives no result and the same error.
That's because the version value is a string and not a number. Just specifying 2.0 is interpreted as a number. Wrap it with quotes like "2.0" and it would work fine.

Categories

Resources