Swagger Is not able to produce documentation for HTTP "PATCH" - java

I Have followed the below
blog entry:
http://kingsfleet.blogspot.co.uk/2014/02/transparent-patch-support-in-jax-rs-20.html
https://github.com/jersey/jersey/tree/2.6/examples/http-patch
To create end point to support HTTP "PATCH" method in Jersey 2.6
Dependency Versions:
-Jersey: 2.6
-swagger-jersey2-jaxrs_2.10: 1.3.12
Question?
Why Patch end point is not getting listed as part of the swagger ui documentation?
Analysis:
If I am annotating with this annotation, then documentation for that end point getting generated, but no interaction .
#com.wordnik.swagger.jaxrs.PATCH
Configurations
JerssyApplicationInitializer
packages(true, "com.test.account.endpoint", "com.wordnik.swagger.jaxrs.json");
//Swagger Configuration
register(new ApiListingResourceJSON(), 10);
register(JerseyApiDeclarationProvider.class);
register(JerseyResourceListingProvider.class);
//Genson Converter
register(GensonJsonConverter.class, 1);
register(createMoxyJsonResolver());
I am not sure, if I am missing something, any help or guide will be helpful.
Patch method doscumets:
public static final String PATCH_MEDIA_TYPE = "application/json-patch+json";
#PATCH
//#com.wordnik.swagger.jaxrs.PATCH
#PreAuthorize(userAuthenticationRequire=true)
#Consumes(PATCH_MEDIA_TYPE)
#Path("{id: .\\d+}")
#ApiOperation(value = "Update Client Details in UIM System."
, response = State.class
, notes="Requesting User, should be the owner of the Client."
, consumes = PATCH_MEDIA_TYPE)
#ApiResponses({
#ApiResponse(code = _401, message = "If the access token is invalid.", response = String.class),
#ApiResponse(code = _498, message = "If the access token is expired.", response = String.class),
#ApiResponse(code = _420, message = "If Provided Input is not valid according to requirment specification."),
#ApiResponse(code = _404, message = "If no client/app Found."),
#ApiResponse(code = _200, message = "If Client Account has been Updated successfully. ", response=String.class)
})
public State updateClientDetails(#ApiParam(value="Client Id to be Updated.", required=true) #PathParam(CLIENT_ID) String clientId
, #ApiParam(value = "Updated field and Value.", required = true) final State newState){
//LOG.info("[ENTRY]- Received requst for updating Client {} from System.", clientId);
System.out.println("----->" + someBean.test());
//LOG.info("[EXIT]- Client Id {} Updation has been completed.", clientId);
Test t = new Test();
t.name = "Hello Test";
System.out.println(t.name);
return newState;
}

Take a look at your index.html. That controls which HTTP operations are interactive--by changing it to this:
window.swaggerUi = new SwaggerUi({
url: url,
dom_id: "swagger-ui-container",
supportedSubmitMethods: ['get', 'post', 'put', 'delete', 'patch'],
You will have interaction on the PATCH method:

Related

How to set example values in #ApiModelProperty in such a way that different values are returned for HTTP status codes?

I have a class called ErrorDetails which is a template for all error responses.
public class ErrorDetails {
private Date timestamp;
private String message;
private String details;
private int code;
public ErrorDetails(Date timestamp, String message, String details, int code) {
this.timestamp = timestamp;
this.message = message;
this.details = details;
this.code = code;
}
}
Now, in order to display example values, we use swagger annotations: #ApiModel & #ApiModelProperty . But I want to display different samples for respective error responses.
For example, code 400, should have sample message: Page not found and for code 500 will ahve different sample message. How do I achieve that? I can only specify one example value for a specific case. Is there a way to programmatically handle sample values? I have explored below ways:
Having a generic response set at global docket config:
Problem here is I might have different error response for code 404 alone. For example : "Employee not found", "Store not found" etc. This is impossible to achieve if I have global configuration.
Using #Example with #ApiResponse:
Problem here is this is not working & springfox dev team suggest to use #ApiModelProperty instead of this approach.
#ApiResponse(code = 500, message = "Internal server error", response = ErrorDetails.class, examples = #Example(value = #ExampleProperty(value = "{\"timestamp\": \"1598947603319\", \"message\":\"Operation failed\", \"details\":\"Operation failed due to Runtime exception\", \"code\": \"500\"}", mediaType = "application/json")))
The above code is not working and I get the below output:
Can someone suggest me how to fix the above issue ? or how to set values dynamically in #ApiModelProperty ?
If you need to only display what message is attached to which status code, then here's example
#PostMapping(value = "/api/posts")
#ApiOperation(value = "Create post.")
#ApiResponses({
#ApiResponse(code = 200, message = "Post created successfully", response = PostResponse.class),
#ApiResponse(code = 404, message = "Blog does not exist", response = ApiError.class),
#ApiResponse(code = 409, message = "Post already exists", response = ApiError.class),
#ApiResponse(code = 422, message = "Block content full", response = ApiError.class)
})
PostResponse createPost(...){
...
}
Apparently, I had to create different classes representing each one of these errors and link them from #ApiResponse. There's no way that I can have one single model class that can throw varying sample responses for all different HTTP status.

Get jwt-claims in a stateless spring-webflux service

Is there an easy way to pick up a jwt-claim in an endpoint built via swagger for a stateless spring-webflux-resource-service without having to manually pick the token from the header and parse it again as it is already done by the framework?
The method definition is similar to this (generated via openapi-generator-maven-plugin):
#Validated
#Api(value = "seller", description = "the seller API")
public interface SellerApi {
#ApiOperation(value = "gets all pricing models for sellers", nickname = "sellerPricingModels", notes = "provides a list of pricing models for the sellers", response = RestPricingModel.class, responseContainer = "List", tags={ "seller","pricing-models", })
#ApiResponses(value = {
#ApiResponse(code = 200, message = "picked up all the pricing models from the database", response = RestPricingModel.class, responseContainer = "List"),
#ApiResponse(code = 401, message = "unauthorized", response = RestErrorBody.class) })
#RequestMapping(value = "/seller/pricing-models",
produces = { "application/json" },
method = RequestMethod.GET)
default Mono<ResponseEntity<Flux<RestPricingModel>>> sellerPricingModels(#ApiParam(value = "" ,required=true) #RequestHeader(value="Language-Code", required=true) String languageCode, ServerWebExchange exchange) {
Mono<Void> result = Mono.empty();
exchange.getResponse().setStatusCode(HttpStatus.NOT_IMPLEMENTED);
...
return result.then(Mono.empty());
}
}
I am using as authentication provider auth0 and I am testing it using their downloadable angular sample. I authenticated myself, I can see the token with the correct claims in auth0 debugging console, I can see the claims loaded fine in my test-ui but I am stuck fetching the claims from the token.
What I am trying to do is to have this stateless service and when an authenticated user tries to access an endpoint (i.e. /seller/pricing-models), I want to fetch only resources for this user. To have this done, I need to pick the user-id from the claims. This is not impossible, but I was wondering if I use something already provided by spring. Ideally, this would be something that does not require me to modify the method as it is automatically generated or at least to configure the openapi-generator-maven-plugin to insert it there.

How to test a Jersey endpoint without additional frameworks

I am developing jersey endpoints and I have to do the integration test for this endpoints, my doubt is how can I make the unit test for this endpoint without adding more dependencies to the pom or additional libraries, because it is a restriction. There is a way to achieve that? I am using junit version 5. This is an example of my endpoint. I was using jerseyTest but I had to revert my changes, because of the restriction:
#GET
#Path("/")
#ApiResponses(value = {
#ApiResponse(code = SC_OK, response = HorasPaginatedResult.class,
message = "Successfully retrievedHoras from Labor Service"),
#ApiResponse(code = SC_BAD_REQUEST, response = ErrorMessage.class, message = "The request was malformed or missing a required field"),
#ApiResponse(code = SC_INTERNAL_SERVER_ERROR, response = ErrorMessage.class, message = "There was an issue processing the request and the server has failed out of the action"),
})
#ApiOperation(value = "Used to query the time service for timeclocks.",
response = HorasPaginatedResult.class,
tags = "Horas",
nickname = "get-Horas.all")
public PaginatedResult<Horas> getHorasAll(
#Nullable #ApiParam("the token to the next page of results") #QueryParam("token") String token,
#Nullable #ApiParam(value = "the field to sort by - this may through a 500 error if the index does not exsist", example = "timestamp") #QueryParam("sortBy") String sortBy,
#Nullable #ApiParam("boolean to determine which direction the sort should be in") #QueryParam("sortAscending") Boolean sortAscending,
#Nullable #ApiParam("the maximum number of 'records' to return per page") #QueryParam("recordLimit") Integer recordLimit,
#Nullable #ApiParam(value = "object", example = "%7B%22field%22%") #QueryParam("expression") List<Query.Expression> expressions) {
Query query;
if (token != null) {
query = new Query(token);
} else {
query = new Query(sortBy, recordLimit, sortAscending);
if (expressions != null) {
expressions.forEach(query.getExpressions()::add);
}
}
logger.info("creating query of {}", query);
return HorasService.getHoras(query);
}
private static class HorasPaginatedResult extends PaginatedResult<BanquetLaborHoras> {
}
Any ideas?

File Upload on Swagger Controller Interface

I'm creating an API micro-service that provides file storage with AWS. I'm putting together the Swagger and Controller, and we need to be able to allow users to upload a file on the Swagger. The problem is our controller is set up as an interface instead of a class, and solutions from Google/SO aren't making the cut to be able to work with interfaces. To clarify, I don't need to manipulate the file at all, just take it in. Our internal implementation methods will take then send it off to S3.
This is using Java 11, AWS S3, Spring Boot, and Swagger 2. I've tried using #ApiParam and #FormDataParam inside the method createFile, but I've gotten two different errors:
method must be abstract
annotations are not allowed here.
#RequestMapping(value = {"v3/registration/documents", "v4/registration/documents"})
#RestController
#Api(
value = "file-storage",
description = "File storage service",
tags = {"file-storage"})
public interface FileController {
#PostMapping(
value = "/{salesPlanAff}",
produces = {MediaType.APPLICATION_JSON_VALUE},
consumes = {MediaType.APPLICATION_JSON_VALUE})
#ApiOperation(value = "Upload a file")
#ApiResponses(
value = {
#ApiResponse(code = 200, message = "Success", response = FileResponseDTO.class),
#ApiResponse(code = 201, message = "Created"),
#ApiResponse(code = 400, message = "Bad Request"),
#ApiResponse(code = 401, message = "Unauthorized"),
#ApiResponse(code = 403, message = "Forbidden"),
#ApiResponse(code = 404, message = "Not Found"),
#ApiResponse(code = 500, message = "Internal Server Error")
})
void createFile(
#PathVariable(required = true, name = "webSessionId") String webSessionId,
#PathVariable(required = false, name = "salesPlanAff") String salesPlanAff);
What I expected is to have a button on my swagger page allowing file upload, didn't quite expect this much difficulty in adding file upload.
I have a FileUpload in my swagger page and it works like a charm. The only difference from your is that I am not doing it on an interface...
import org.springframework.web.multipart.MultipartFile;
...
#ApiOperation(value = "Analyse the identifiers in the file")
#RequestMapping(value = "/form", method = RequestMethod.POST, produces = "application/json")
#ResponseBody
public AnalysisResult getPostFile( #ApiParam(name = "file", value = "The file")
#RequestPart MultipartFile file,
HttpServletRequest r) {
UserData ud = controller.getUserData(file);
return controller.analyse(ud, r, file.getOriginalFilename());
}
I trimmed off a little bit this code, but you can find a the original one in our repository
Also, working version of this code can be executed tested here
Thanks
I figured out how to get the annotations in, part of it stemmed from typos. For anyone interested, here's the solution:
public interface FileController {
#PostMapping(
value = "/{salesPlanAff}",
produces = {MediaType.APPLICATION_JSON_VALUE},
consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
#ApiOperation(value = "Upload a file")
#ApiResponses(
value = {
#ApiResponse(code = 200, message = "Success", response = FileResponseDTO.class),
#ApiResponse(code = 201, message = "Created"),
#ApiResponse(code = 400, message = "Bad Request"),
#ApiResponse(code = 401, message = "Unauthorized"),
#ApiResponse(code = 403, message = "Forbidden"),
#ApiResponse(code = 404, message = "Not Found"),
#ApiResponse(code = 500, message = "Internal Server Error")
})
void createFile(
#PathVariable(required = true, name = "webSessionId") String webSessionId,
#PathVariable(required = false, name = "salesPlanAff") String salesPlanAff,
#ApiParam(required = true, value = "Document to be uploaded")
#RequestPart MultipartFile multipartFile,
#ApiParam(required = true, value = "File Type")
#QueryParam("documentType") String documentType);

Can not upload file when using a swagger generated spring server

I want to implement a file readout function on my REST Service. Since I do not know how to use spring myself, I use swagger to generate the server code for me. Normally this works perfectly fine, but when I try to upload files I get the following error:
{
"timestamp": "2018-11-07T12:27:43.119Z",
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.web.multipart.support.MissingServletRequestPartException",
"message": "Required request part 'file' is not present",
"path": "/requirements/import"
}
My yaml uses the following lines for the import function:
/requirements/import:
post:
consumes:
- multipart/form-data
description:
Returns all requirements contained in the submitted reqIf file.
parameters:
- name: reqIfFile
in: formData
type: file
description: The reqIf file that contains the requirements.
responses:
200:
description: An array of requirements.
schema:
type: array
items:
$ref: 'requirement'
The generated interface (with some added exceptions):
#javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-04-05T07:19:00.887Z")
#Api(value = "requirements", description = "the requirements API")
public interface RequirementsApi {
#ApiOperation(value = "", nickname = "requirementsImportPost", notes = "Returns all requirements contained in the submitted reqIf file.", response = Requirement.class, responseContainer = "List", tags = {})
#ApiResponses(value = {
#ApiResponse(code = 200, message = "An array of requirements.", response = Requirement.class, responseContainer = "List") })
#CrossOrigin(origins = "*")
#RequestMapping(value = "/requirements/import", produces = { "application/json" }, consumes = {
"multipart/form-data" }, method = RequestMethod.POST)
ResponseEntity<List<Requirement>> requirementsImportPost(
#ApiParam(value = "file detail") #Valid #RequestPart("file") MultipartFile reqIfFile)
throws IOException, ContinuumException;
}
The code that actually does the readout:
#javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-04-05T07:19:00.887Z")
#Controller
public class RequirementsApiController implements RequirementsApi {
#Override
public ResponseEntity<List<Requirement>> requirementsImportPost(
#ApiParam(value = "file detail") #Valid #RequestPart("file") final MultipartFile reqIfFile)
throws IOException, ContinuumException {
InputStream fileStream = new BufferedInputStream(reqIfFile.getInputStream());
List<Requirement> list = ReadReqIF.readReqIfFile(fileStream);
return new ResponseEntity<List<Requirement>>(list, HttpStatus.OK);
}
}
Can someone tell me where a possible error is?
I encountered the same problem with my swagger generated spring server.
I was able to workaround the problem by modifying the generated server code to change the name "file" in #RequestPart("file") to the name specified in the swagger spec. In your case, it should be #RequestPart("reqIfFile"). It'd have to be modified in both the interface and controller code.
There is likely a bug in the Spring server generator code in Swagger editor. I can't think of any other reason for the RequestPart annotation to be named "file" which is essentially the "type" and not name of the parameter.

Categories