How to create multiple schema in #RequestBody of swagger openapi specification 3.0 using springdoc? - spring-boot

I have the below api for which I need to have two parameters of content type application/x-www-form-urlencoded and therefore am using #RequestBody instead of #Parameter
#Operation(summary = "Revoke given permissions", description = "Allows admin to revoke permissions to users")
#RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public void revokePermission(
#RequestBody(description = "the permission id", content = #Content(mediaType = "application/x-www-form-urlencoded",
schema = { #Schema(type = "String", name = "permission_id",
description = "id of the permission to be revoked", required = true)},
{ #Schema(type = "String", name = "permission_type",
description = "the permission type")}))
String permission_id, String permissionType) {
do_something();
}
I need the swagger.json to be like below example, but I do not know how to generate it using springdoc .I tried #ArraySchema also , but I am not getting the output I need. I am making some mistakes in the syntax and not able to find examples online.
"requestBody": {
"content": {
"application/x-www-form-urlencoded": {
"schema": {
"properties": {
"permission_id": {
"description": "id of the permission to be revoked",
"type": "string"
},
"permission_type": {
"description": "the permission type",
"type": "string"
}
},
"required": ["permission_id"]
}
}
}
}
Any help is highly appreciated. TIA

The The simplest way to achieve what you want is to define the permission data in simple object as follow:
#Schema(name = "permissionData")
public class PermissionData {
#Schema(type = "String", name = "permiddionId", description = "id of the permission to be revoked", required = true)
#JsonProperty("permiddionId")
String permiddionId;
#Schema(type = "String", name = "permissionType",description = "the permission type")
#JsonProperty("permissionType")
String permissionType;
}
And then you controller method:
#Operation(summary = "Revoke given permissions", description = "Allows admin to revoke permissions to users")
#RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public void revokePermission(#RequestBody(description = "the permission data") PermissionData permissionData) {
}

Related

What is the Swagger 2 Annotation for the responseContainer?

I working on a Migration from Springfox to Springdoc with Swagger version 2.1.9.
Therefore the Annotations must be rewritten and I cant find the equivalent Annotations for the old Swagger Annotations.
I have this API Controller:
#GetMapping
#ApiOperation(value = "Load Building")
#ApiResponses(value = {
#ApiResponse(code = 200, message = "OK", response = Building.class, responseContainer = "Page")
})
public ResponseEntity<Page<Building>> getBuilding(Pageable building) {
final Page<Building> building = buildingrepo.findAll(page).map(bw -> mapper.map(bd, Building.class));
return ResponseEntity.ok().body(building);
With the new Swagger Annotation it must be re-written, but I don`t know how i put the "Building.class" into the Pageable in the Response Schema. I cant use "responseContainer" anymore
#GetMapping
#Operation(summary = "Load Building")
#ApiResponses(value = {
#ApiResponse(responseCode = "200",
description = "OK",
content = #Content(schema = #Schema(implementation = Building.class))) // <--- Here i need the Page class somehow as Container!!!
})
public ResponseEntity<Page<Building>> getBuilding(Pageable building) {
final Page<Building> building = buildingrepo.findAll(page).map(bw -> mapper.map(bd, Building.class));
return ResponseEntity.ok().body(building);
The Output Response in the Api Docs schould look like this:
responses:
200:
schema:
$ref: "#/definitions/Page<Building>"
And also in the Swagger UI as Example:
{
"content": [
{ Building: "" }
]
}
I cant find the right Parameter for the "responseContainer"
Swagger 2's equivalent to a responseContainer is to wrap the Schema in an ArraySchema. For an endpoint returning List<Foo> :
#ApiResponses(#ApiResponse(responseCode = "200", description = "List of Foos",
content = #Content(array = #ArraySchema(uniqueItems = false,
schema = #Schema(implementation = com.mycompany.Foo.class))
)))
Note uniqueItems is false by default so can be omitted above. However, explicitly set this value to true if you're returning a Set instead of a List.
References:
https://docs.swagger.io/swagger-core/v2.1.1/apidocs/io/swagger/v3/oas/annotations/media/ArraySchema.html

Unable to show Custom Header in Open API UI

How to set Custom Header when using Open API 3? I am using Spring Boot + springdoc-openapi-ui example. In this example I am looking to pass the different headers in the request. Below configurations doesn't show option to select the customer header.
What else do I need to change?
#Bean
public OpenAPI customOpenAPI(#Value("${springdoc.version}") String appVersion) {
return new OpenAPI()
.components(new Components().addSecuritySchemes("basicScheme", new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("basic"))
.addParameters("myHeader1", new Parameter().in("header").schema(new StringSchema()).name("myHeader1")).addHeaders("myHeader2", new Header().description("myHeader2 header").schema(new StringSchema())))
.info(new Info()
.title("Petstore API")
.version(appVersion)
.description("This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.")
.termsOfService("http://swagger.io/terms/")
.license(new License().name("Apache 2.0").url("http://springdoc.org")));
}
You can add your custom Header to your operation documentation using the Following annotation #Parameter(in = ParameterIn.HEADER).
For example:
#RestController
#RequestMapping("/api")
#Tag(name = "contact", description = "the Contact API")
public class HelloController {
#Operation(summary = "Find Contacts by name", description = "Name search by %name% format", tags = {"contact"})
#ApiResponses(value = {
#ApiResponse(responseCode = "200", description = "successful operation", content = #Content(array = #ArraySchema(schema = #Schema(implementation = PersonDTO.class))))})
#Parameter(in = ParameterIn.HEADER, description = "Custom Header To be Pass", name = "Accept-version"
, content = #Content(schema = #Schema(type = "string", defaultValue = "v1", allowableValues = {"v1", "v2"}, implementation = PersonDTO.class)))
#GetMapping(value = "/contacts", /*produces = { "application/json", "application/xml" },*/ headers = {"Accept-version=v10"})
public ResponseEntity<List<PersonDTO>> findAll(
#Parameter(description = "Page number, default is 1") #RequestParam(value = "page", defaultValue = "1") int pageNumber,
#Parameter(description = "Name of the contact for search.") #RequestParam(required = false) String name) {
return null;
}}
SOLVED: To have header parameters applied to all requests:
All the suggestions I found didn't work and did some digging and found this solution below:
#Bean
public GlobalOpenApiCustomizer customizer() {
return openApi -> openApi.getPaths().values().stream().flatMap(pathItem -> pathItem.readOperations().stream())
.forEach(operation -> operation.addParametersItem(new HeaderParameter().name("[YOUR_NAMR]")
.description("[YOUR_DESC]")
.in(ParameterIn.HEADER.toString())
.schema(new Schema<>().format("[e.g UUID]").type("[e.g STRING]")) //will be: string($uuid)
.required(true)));
}
Found the solution here: https://springdoc.org/faq.html

How to remove unwanted keys from rest-assured response object and assert remaining object data with constant variable having json string using java

In rest-assured test cases I am getting response as mentioned, where I want to remove keys such as "updated_at", "deleted_at", "created_at" and "notice" and then assert this response object with expected json string constant which contains 'settings'
{
"notice": "The Settings are updated successfully.",
"settings": {
"push_notification": {
"enabled": true,
"credentials": [{
"key": "value"
}],
"service_name": "API Testing"
},
"created_at": "2019-05-04T14:52:32.773Z",
"deleted_at": "false",
"updated_at": "2019-05-07T11:23:22.781Z"
}
}
For given response the expected json string is...
public static String SETTING_EXPECTED = "{\"push_notification\": {\"enabled\": true, \"credentials\": [{\"key\": \"value\"}], \"service_name\": \"API Testing\"}}"
Please help me with creating a common method using java which can be reuse for response assertions in all the test cases.
To delete keys from response you can use below code I am using jayway jsonpath library, you need to pass Json Response and field name jsonPath, in case your it will be "$.settings.created_at" :
public String deleteFieldNameFromResponse(String jsonResponse, String fieldToDelete)
throws ParseException, FileNotFoundException, IOException {
Object obj = null;
JSONParser parser = new JSONParser();
JsonPath jsonPath = null;
DocumentContext docCtx = null;
obj = parser.parse(jsonResponse);
docCtx = JsonPath.parse(obj);
docCtx.delete(fieldToDelete);
jsonPath = JsonPath.compile("$");
return docCtx.read(jsonPath).toString();
}

Consuming REST Service in Spring

I'm frightfully new to Spring and Java but I'm trying to consume some code for some rule validations in Easy Rules but I can't quite figure it out.
#RequestMapping(method = {RequestMethod.GET}, value = "author/field", produces= MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody ResponseEntity<Enum> getField(#RequestParam(value="field", required=true) String field){
Enum enum = mongoService.findByField(field);
if(enum == null){
return new ResponseEntity<Enum>(HttpStatus.NO_CONTENT);
}else{
return new ResponseEntity<Enum>(enum,HttpStatus.OK);
}
}
So I'm trying something like:
import com.mongoservice.Enum
import com.mongoservice.Enums
RestTemplate restTemplate = new RestTemplate();
String uri = "http://localhost:9000";
//This is my confusion
List<Enums> response = restTemplate.getForObject(uri +
"/author/field?={field}", Enum.class,"a").getEnums();
String value = response.getValue().toString().trim();
//this is the record i'm checking against that is pulling a specific string value and what i'm expecting
String record = "a";
return (value == record);
The JSON data I'm trying to pull back is modeled like this but I need to validate to make sure that record equals one of the values from enums[] json array
{
"field": "a",
"descriptor": "blah",
"enums": [
{
"value": "h",
"description": "blah"
},
{
"value": "e",
"description": "blah"
},
{
"value": "l",
"description": "blah"
},
{
"value": "p",
"description": "blah"
}
]
}
What is the problem that you are seeing is it just not matching? If so it could be because you are using == instead of String.equals. Try modifying your code to:
return record.equals(value);
See Java String.equals versus == for more.
Can you change String uri = "http://localhost:9000"
and missed the path variable name field it should be like author/field?field={field} as per your controller description.

HttpMediaTypeNotAcceptableException when application/json-patch+json is used as 'Content-Type' header

we are using patch operation to support partial update.
#ApiOperation(value="Patch (Partial Update) user payment")
#RequestMapping(method = RequestMethod.PATCH, consumes = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<UserPaymentInfo> patchPaymentInfo(#ApiParam(value = "The user id", required = true)#PathVariable final String uid,
#ApiParam(value = "Whether to reteurn new payment info back") #RequestParam(name = "includeResponse", defaultValue = "false") final boolean includeResponse,#ApiParam(value = "Description of changes")#RequestBody final String userPaymentInfoPatchJson) {
UserPaymentInfo paymentInfo = userPaymentService.patchPaymentInfo(uid,userPaymentInfoPatchJson,includeResponse);
HttpStatus status = includeResponse ? HttpStatus.OK : HttpStatus.NO_CONTENT;
return new ResponseEntity<>(paymentInfo,status);
}
Below mentioned is exception :
{"code": "0000",
"message": "Could not find acceptable representation (HttpMediaTypeNotAcceptableException)",
"host": "localhost",
"url": "/users/000020800464/paymentinfo/test",
"method": "PATCH",
"causes": [
{
"code": "0000",
"message": "Could not find acceptable representation (HttpMediaTypeNotAcceptableException)"
}
]
}
The same endpoint works good for application/json as header value of Content-Type but 'application/json-patch+json' fails.
Does spring boot support patch bcs i am not able to find related header name mentioned in org.springframework.http.MediaType.java

Resources