Swagger annotations describe default response of an operation - java

I want to define "default" response of an operation with #ApiResponse annotation.
I'm using swagger annotations 1.5.x and want to generate something like this (look at default response):
"get" : {
...
"responses" : {
"200" : {
"description" : "successful operation",
"schema" : {
"type" : "array",
"items" : {
"$ref" : "#/definitions/Address"
}
}
},
"default" : {
"description" : "unsuccessful operation",
"schema" : {
"$ref" : "#/definitions/ErrorResponse"
}
}
},
...
}
But I don't know how to do that, because #ApiResponse(code = ...) annotation expects only numbers not Strings.
My Java code:
...
#ApiResponses(value = {
#ApiResponse(code = 200, message = "successful operation", response = Address.class, responseContainer = "List"),
#ApiResponse(code = "default", message = "unsuccessful operation", response = ErrorMessage.class),
...})
public Response getAllAddresses() throws SQLException {
...
}
So is there any way to specify "default" ApiResponse in Swagger annotations 1.5.x?

Related

How to get OpenApi Generator for Spring Java server generate ResponseEntity<Object> for PUT request?

I am using the 4.3.1 version of the openapi-generator-maven-plugin to generate a SpringBoot server in Java 11.
For a PUT request I want to be able to return the URI to the created/updated object when successful, and plain text with information about the problem when unsuccessful.
My json for the API has the following content for the PUT request:
"put": {
"summary": "Create or update a Service",
"deprecated": false,
"operationId": "putIndividualServiceUsingPUT",
"responses": {
"200": {
"description": "Service updated"
},
"201": {
"description": "Service created",
"content": {
"text/plain": {
"schema": {
"type": "string",
"example": "services/DroneIdentifier"
}
}
}
},
"400": {
"description": "Provided service is not correct",
"content": {
"text/plain": {
"schema": {
"type": "string",
"example": "Service is missing required property version"
}
}
}
},
"401": {
"description": "Unauthorized"
},
"403": {
"description": "Forbidden"
}
},
"parameters": [
{
"name": "serviceName",
"in": "path",
"required": true,
"schema": {
"type": "string"
},
"example": "DroneIdentifier"
}
],
"requestBody": {
"description": "Service to create/update",
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/service"
}
}
}
}
The generated API:
/**
* PUT /services/{serviceName} : Create or update a Service
*
* #param serviceName (required)
* #param service Service to create/update (required)
* #return Service updated (status code 200)
* or Service created (status code 201)
* or Provided service is not correct (status code 400)
* or Unauthorized (status code 401)
* or Forbidden (status code 403)
*/
#ApiOperation(value = "Create or update a Service", nickname = "putIndividualServiceUsingPUT", notes = "", tags={ "rAPP Catalogue API", })
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Service updated"),
#ApiResponse(code = 201, message = "Service created", response = String.class),
#ApiResponse(code = 400, message = "Provided service is not correct", response = String.class),
#ApiResponse(code = 401, message = "Unauthorized"),
#ApiResponse(code = 403, message = "Forbidden") })
#RequestMapping(value = "/services/{serviceName}",
produces = { "text/plain" },
consumes = { "application/json" },
method = RequestMethod.PUT)
default ResponseEntity<Void> putIndividualServiceUsingPUT(#ApiParam(value = "",required=true) #PathVariable("serviceName") String serviceName,#ApiParam(value = "Service to create/update" ,required=true ) #Valid #RequestBody Service service) {
return getDelegate().putIndividualServiceUsingPUT(serviceName, service);
}
However, the return type of the method is ResponseEntity<Void>, which means that I am not able to put anything in the body of the response.
Am I doing something wrong? Or is the generator hard coded to not permit a body in the response of a PUT request?
Generated code templates are stored as resources in the .mustache format. But you can easily overwrite it by creating a modified file with the same name and adding a link to the folder if you have Maven or Gradle.
In your case, copy the api.mustache and methodBody.mustache files to your computer or project resources from https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator/src/main/resources/Java, and change them by replacing Response<> with a URI.
Add the item <templateResourcePath>folderInYourResources</templateResourcePath> or <templateDirectory>pathToDirectory</templateDirectory>
into your Maven <configuration> and everything should work

Jersey project Swagger-UI doesn't send #HeaderParam while #PathParam is sent

Java Jersey project using following Swagger Core:
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-jaxrs2</artifactId>
<version>2.0.2</version>
</dependency>
the document link goes to "openapi.json". Swagger-UI dist ver 3.20.5 is downloaded from here. Java code is like this:
#Path("/auth")
public class TestConttroller {
#GET
#Path("/{id}")
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response testGet(
#DefaultValue("") #HeaderParam("Authorization") String a,
#DefaultValue("") #PathParam("id") String id)
{
return Response.ok().build();
}
When sending request from Postman everything works. But when from following Swagger-UI, the header-param string "a" is an empty string while the path-param string is good. The part in openapi.json is here:
"paths" : {
"/auth/{id}" : {
"get" : {
"operationId" : "testGet",
"parameters" : [ {
"name" : "Authorization",
"in" : "header",
"schema" : {
"type" : "string",
"default" : ""
}
}, {
"name" : "id",
"in" : "path",
"required" : true,
"schema" : {
"type" : "string",
"default" : ""
}
} ],
"responses" : {
"default" : {
"description" : "default response",
"content" : {
"application/json" : { },
"application/xml" : { }
}
}
}
}
}
Check with WireShark found the header is not in request at all. Should the problem in Swagger-UI?
#HeaderParam("Authorization") is like a keyword of HTTP? when I used other name like "Auth" then it works.

swagger core 2.0 disable security for endpoint

I am using Swagger Core 2.0 to generate openAPI 3.0 definition files and
I am having trouble to disable "security" for a particular endpoint.
I have my securitySchemes and root security element defined:
{
"openapi" : "3.0.1",
"security" : [ {
"JWT" : [ ]
} ],
"paths" : {
"/auth" : {
"post" : {
"summary" : "authenticate user",
"operationId" : "authenticate",
"requestBody" : {
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/AuthenticationRequest"
}
}
}
},
"responses" : {
"200" : {
"description" : "when user is successfully authenticated",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/AuthenticateUserOutput"
}
}
}
},
"401" : {
"description" : "when email/password not valid or user is blocked/inactive"
}
}
}
},
},
"components" : {
"schemas" : {
"AuthenticateUserOutput" : {
"type" : "object",
"properties" : {
"token" : {
"type" : "string"
},
"lastLoginAt" : {
"type" : "string",
"format" : "date-time"
},
"lastProjectId" : {
"type" : "string"
}
}
},
...,
"AuthenticationRequest" : {
"required" : [ "email", "password" ],
"type" : "object",
"properties" : {
"email" : {
"type" : "string"
},
"password" : {
"type" : "string"
}
}
}
},
"securitySchemes" : {
"JWT" : {
"type" : "http",
"scheme" : "bearer",
"bearerFormat" : "JWT"
}
}
}
}
According to OPEN API 3 spec https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#securityRequirementObject i shall be able to override global "security requirement" for an individual operation. I would like to "disable" JWT security for a few operations and according to https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#securityRequirementObject it can be done:
To remove a top-level security declaration, an empty array can be used.
Unfortunately I am struggling to define "empty security array" on Operation level using annotations...
I tried to specify
security = {}
or
security = #SecurityRequirement(name ="")
but no security element within operation is generated at all....
Any idea ?
Below is my java code (i use for swagger dropwizard integration) that allows one to have SecurityScheme and root level security defined
Info info = new Info()
.title("someTitle")
.description("some description")
.version("1.0")
SecurityScheme jwtSecurity = new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.name("Authorization")
.in(SecurityScheme.In.HEADER)
.scheme("bearer")
.bearerFormat("JWT");
String securitySchemaName = "JWT";
OpenAPI oas = new OpenAPI()
.info(info)
.components(new Components().addSecuritySchemes(securitySchemaName, jwtSecurity))
.addSecurityItem(new SecurityRequirement().addList(securitySchemaName));
SwaggerConfiguration oasConfig = new SwaggerConfiguration()
.openAPI(oas)
.prettyPrint(true)
.resourcePackages(Stream.of("my.resources.package")
.collect(Collectors.toSet()));
environment.jersey().register(new OpenApiResource()
.openApiConfiguration(oasConfig));
Then on a few dedicated endpoints i would like to disable security, so i am trying with:
#POST
#Operation(
summary = "authenticate user",
responses = {
#ApiResponse(responseCode = "200", description = "when user is successfully authenticated",
content = #Content(schema = #Schema(implementation = AuthenticateUserOutput.class))),
#ApiResponse(responseCode = "401", description = "when email/password not valid or user is blocked/inactive"),
}
,security = what to put here ?
)
if you want to do it in yml swagger hub style you can put
security: []
in that endpoint after request body, So swagger considers it as no auth for that particular path or endpoint.
According to a comment over on the OpenAPI-Specifiction GitHub project. It should be possible.
Did you try this?
security: [
{}
]
I had the same problem, on a Java SpringBoot webapp (dependency org.springdoc:springdoc-openapi-ui:1.5.2). As per this answer, I solved it adding an empty #SecurityRequirements annotation on the operation. For example:
#POST
#SecurityRequirements
#Operation(
summary = "authenticate user",
responses = {
#ApiResponse(responseCode = "200", description = "when user is successfully authenticated",
content = #Content(schema = #Schema(implementation = AuthenticateUserOutput.class))),
#ApiResponse(responseCode = "401", description = "when email/password not valid or user is blocked/inactive"),
} )
)

How to consume Spring HATEOAS REST resources containing links to another resources?

I have /studentCourses endpoint on the server (built with Spring Data REST) which returns the following content:
{
"_embedded" : {
"studentCourses" : [
{
"uid" : "5f23abe9-b24e-4e76-86b0-d539950a0a41",
"registrationDate" : "7/23/2016",
"_links" : {
"self" : {
"href" : "http://localhost:8080/studentCourses/5f23abe9-b24e-4e76-86b0-d539950a0a41"
},
"studentCourse" : {
"href" : "http://localhost:8080/studentCourses/5f23abe9-b24e-4e76-86b0-d539950a0a41"
},
"course" : {
"href" : "http://localhost:8080/studentCourses/5f23abe9-b24e-4e76-86b0-d539950a0a41/course"
},
"student" : {
"href" : "http://localhost:8080/studentCourses/5f23abe9-b24e-4e76-86b0-d539950a0a41/student"
}
}
},
{
...
},
...
]
},
"_links" : {
"self" : {
"href" : "http://localhost:8080/studentCourses"
},
"profile" : {
"href" : "http://localhost:8080/profile/studentCourses"
}
},
"page" : {
...
}
}
And the following client code:
class StudentCourseDTO {
String uuid;
String registrationDate;
StudentDTO student; // contains uuid, firstName, lastName, etc.
CourseDTO course; // contains uuid, name, etc.
// getters, setters
}
RestTemplate restTemplate() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new Jackson2HalModule());
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MappingJackson2HttpMessageConverter messageConverter =
new MappingJackson2HttpMessageConverter();
messageConverter.setObjectMapper(objectMapper);
messageConverter.setSupportedMediaTypes(Arrays.asList(MediaTypes.HAL_JSON));
return new RestTemplate(Arrays.asList(messageConverter));
}
...
Collection<StudentCourseDTO> studentCourses = restTemplate().exchange(
"http://localhost:8080/studentCourses",
HttpMethod.GET, null,
new ParameterizedTypeReference<PagedResources<StudentCourseDTO>>() {})
.getBody().getContent();
The problem is that StudentCourseDTO.student and StudentCourseDTO.course are always null, but StudentCourseDTO.uuid and StudentCourseDTO.registrationDate are retrieved correctly from the server.
Anyone has an idea what I have missed?
I think there must be someway to tell RestTemplate to automatically follow the links in the returned content like student and course in the example above, but I haven't found a way to do this.
Just because there are links that does not mean they are automatically followed.
I would change the StudentCourseDTO to:
class StudentCourseDTO {
String uuid;
String registrationDate;
}
And then you would deserialize the response to a
PagedResources<Resource<StudentCourseDTO>> studentCourses = restTemplate().exchange(
"http://localhost:8080/studentCourses",
HttpMethod.GET, null,
new ParameterizedTypeReference<PagedResources<Resource<StudentCourseDTO>>>() {})
.getBody().getContent();
For each Resource<StudentCourseDTO> you can then follow the links for studentand course, e.g. by using the RestTemplate to retrieve the resources.
Of course this gives you two additional calls per response item - but the only way to avoid this is to change the service to embed this information in the list resource.

Elasticsearch java api filteredQuery

I have this query used with Exists API from elasticsearch (1.4.4) :
curl -XPOST 'http://elasticsearch:9200/_search/exists' -d '
{
"query": {
"filtered": {
"query": {
"match_phrase": {
"message": "2014-12-04 00:00:01 CET Tx[XXXXXXXX] cmd[INSERT] PID[XXXX] DB[XXXXX] LOG: some log info here ;-) \r"
}
},
"filter": {
"term" : {
"some_field" :"some_value"
}
}
}
}
}'
This works fine (return true when it has to be) but when I tried to do the same with java API like this :
Client client = this.createClient();
QueryBuilder queryBuilder = QueryBuilders.filteredQuery(
QueryBuilders.matchPhraseQuery("message", "the same message"),
FilterBuilders.termFilter("some_field", "some value")
);
System.out.println(queryBuilder.toString());
ExistsResponse response = client.prepareExists("existsMessage")
.setTypes(type)
.setIndicesOptions(IndicesOptions.fromOptions(true, true, true, false))
.setQuery(queryBuilder).execute().actionGet();
System.out.println(response.exists());
client.close();
But the result is always false! So I print the request build by the and it's different than want I wanted. So is there a way to do exactly my first request from source json or other way using api builders?
Edit :
The output of queryBuilder.toString()) :
{
"filtered" : {
"query" : {
"match" : {
"message" : {
"query" : "the same message\r",
"type" : "phrase"
}
}
},
"filter" : {
"term" : {
"some field" : "some value"
}
}
}
}

Categories

Resources