I am new to swagger and using it's documentation. I am currently trying to use swagger to display the request body of a PATCH request. Previously, the parameter of the PATCH method was the DTO of the object that was being updated, which made it very easy to display the attributes of the object (as I am using SpringBoot, and using #Schema worked perfectly). However, now the parameter of the PATCH method is an HttpServletRequest. Instead of displaying the HttpServletRequest in the swagger doc (which seems to automatically be happening), I want to show the DTOs attributes (just as had been done before). I was wondering if there was a way to do that?
Any advice is much appreciated!
I am assuming you are using springdoc-openapi for generating SwaggerUI.
To use this you can use the below Maven dependencies,
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webmvc-core</artifactId>
<version>1.4.2</version>
</dependency>
From v1.1.25 of springdoc-openapi, HttpServletRequest and HttpServletResponse will be added to the list of ignored types.
See below,
https://github.com/springdoc/springdoc-openapi/issues/57
So even if we add HttpServletRequest as a parameter inside the controller method, it will be ignored and will not be displayed in the swagger.
So coming back to your question, to display the model of a class, you can describe another parameter along with HttpServletRequest as below,
#Operation(summary = "Returns a token", description = "Returns A token API", tags = "tokenGeneration", responses = {
#ApiResponse(description = "Successful Operation", responseCode = "200", content = #Content(mediaType = "application/json", schema = #Schema(implementation = Timeresponse.class))),
#ApiResponse(description = "not found Operation", responseCode = "404") })
#PatchMapping("/getTokenPatchRequest")
public ResponseEntity getTokenpatch(HttpServletRequest request, #RequestBody AuthReq2 req) {
log.info("The HttpServlet request header contains the information : " + request.getHeader("Authorization"));
The model class of Auth2 is as below which can describe your example value of username and passwords etc.
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
#Data
public class AuthReq2 {
#Schema(example = "diannamcallister")
private String userName;
#Schema(example = "test")
private String password;
}
Ands finally the swagger page looks like this,
When you enter something in the authorization header, as below,
This can be accessed via the HTTP servlet request via the below code,
log.info("The HttpServlet request header contains the information : " + request.getHeader("Authorization"));
The log entry in the springboot application will look like below,
10:40:01.876 INFO OpenApiController.getTokenpatch:163 - The HttpServlet request header contains the information : stackoverflow
The above answer did not work since adding another parameter to the method broke the functionality of the method itself.
The solution that worked was in the controller to add the content parameter to the #RequestBody annotation:
#RequestBody(description = "Description.",
content = #Content(schema = #Schema(implementation = ObjectDTO.class)));
How to displaying the HttpServletRequest in the swagger doc?
You can set in the configuration of swagger2 ,SwaggerConfig.java
new Docket(DocumentationType.SWAGGER_2)
...
.ignoredParameterTypes(HttpSession.class, HttpServletRequest.class, HttpServletResponse.class)
.build();
Related
I'm newbie to swagger UI development using jersey framework. I'm looking out to resolve the below mentioned issue.
Issue: Unable to remove/hide body parameter from Swagger UI. Please refer the attached swagger-ui screen for details.
Please find my Java source code:
#POST #Path("/createSchedule")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces({ MediaType.APPLICATION_JSON })
#ApiOperation(httpMethod = HttpMethod.POST, value = "Create a new export schedule(s)") #ApiImplicitParams({ #ApiImplicitParam(name = "file", value = "Upload the template (.xlsx) to create schedule(s).", required = true, dataType = "file", paramType = "formData") })
public Response createSchedule(#FormDataParam(value="file") InputStream inputStream, #FormDataParam(value="file") FormDataContentDisposition fileMetaData) throws ScheduleException {
********* Code to process the uploaded file. **********
}
I have used Jersey 2.29.1(jersey-container-servlet) & Swagger 1.5.0 (swagger-jaxrs) API's. Also do let me know how to allow only specific file extensions (like .xlsx) to upload from swagger ui.
Thanks in advance! Cheers!
I have fixed the issue by doing below changes in the code:
Have changed the swagger maven dependency from "swagger-jaxrs" to "swagger-jersey2-jaxrs"
Include "#ApiParam" swagger annotation with resource method parameter as "#ApiParam(hidden = true) #FormDataParam(value = "file") FormDataContentDisposition fileMetaData".
Refer the issue fixed swagger ui screen:
I wrote the piece of code below:
#PostMapping(path = "/process", produces = MediaType.APPLICATION_JSON_VALUE)
#ApiOperation(value = "Get process with given ID", produces = MediaType.APPLICATION_JSON_VALUE,
response = ProcessType.class)
public ResponseEntity<ProcessType> createProcessType(
#RequestBody
#DTO(ProcessTypeDto.class) ProcessType processType
) {
log.info("POST called on /process");
ProcessType processTypeResult;
...
...
}
which works great. But my problem is with swagger. I made a custom annotation #DTO which automatically maps one class to another. But, swagger sees my ProcessType request body and shows examples in the UI of that class rather than ProcessTypeDto. If I delete what swagger shows and POST ProcessTypeDto the code works I would just like swagger to show ProcessTypeDto as the default example for this endpoint as it would break codegen.
Is there a way to manually specify what request body I would like from swaggers POV overriding what my#Requestbody is?
looks like you are not lucky so far, it will be released in version 2.0
here is what you are lookin for https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Annotations#requestbody
or at least you can start using a release candidate
https://mvnrepository.com/artifact/io.swagger/swagger-core
I'm wondering is it possible to build Swagger documentation based only on swagger-core annotations w/o help of any adapters like jax-rs or springfox?
Why asking the question: e.g. when using springfox it relies on Spring annotations like #RequestMapping, #ResponseStatus etc. Imagine I want to specify a POST method which returns 201 by default:
#ApiOperation(value = "some api")
#ApiResponses(value = {
#ApiResponse(code = 201, message = "Created")
})
#RequestMapping(method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
Without the last line springfox will generate the 200 status by default which I don't want to be a part of the spec. And ofc I don't want to add an imperative #ResponseStatus annotation to the controller.
I.e. I want to be in full control of the generated API spec which should rely on swagger core annotations only.
We are using spring data rest via spring boot (v1.3.3) and have the following entity exposed via the standard REST Repository Exporter:
#Document
public class Project {
#Version
private Long version;
#CreatedDate
private LocalDateTime createdDate;
#CreatedBy
private String createdBy;
#LastModifiedDate
private LocalDateTime lastModifiedDate;
#LastModifiedBy
private String lastModifiedBy;
private String name;
//getters and setters omitted
}
A POST to /projects or a PUT to /projects/1234 for instance creates a document with etag/version 0. Another PUT to /projects/1234 overwrites the document even if the client does not provide a version/etag. Furthermore A DELETE on /projects/1234 deletes the document even if the client does not provide a version/etag.
How can I configure spring data rest to update and delete the document if and only if the client provides a valid version/etag?
The API client needs to specify a valid ETag on a header in the request, like this:
If-Match: <value of previous ETag>
By adding this header to the HTTP request, you convert it into a conditional operation that will only be carried out if it satisfies the condition. There are other conditionals such as If-None-Match or If-Modified-Since.
It is the responsibility of the client to add a conditional header.
From the question I understand that you would like the server to disallow any operation that does not provide a valid ETag, but as far as I know Spring Data Rest does not support this.
You can either change your clients to include the proper header (assuming they are under your control), or implement this feature by yourself.
You can take a look at the Reference Documentation for further info.
How to force clients to send etag/version using spring data rest?
Simply put: you can't, unless you write the clients.
How can I configure spring data rest to update and delete the document if and only if the client provides a valid version/etag?
That requires overriding the PUT/DELETE /projects/1234 handlers provided by Spring Data Rest and deal with ETags on your own.
In order to override the handlers, you need to annotate your controller with RepositoryRestController and use RequestMapping at the method level to still benefit from the other handlers provided by Spring.
To handle the ETag part, you can dig in the contents of the request headers (search for the If-* headers mentionned by #ESala by adding a HttpServletRequest paramater to your handlers.
#RepositoryRestController
public class ProjectRepositoryRestController {
#Autowired
private ProjectRepository repository;
#RequestMapping(value = "/projects/{id}", method = RequestMethod.PUT)
#ResponseBody
public Item update(#PathVariable(value = "id") String id, #RequestBody Project, HttpServletRequest request)
{
/* dig into the request headers */
// for instance
String header = request.getHeader("If-match");
// or more likely do something with request.getHeaders(...) or request.getHeaderNames(...) to check if the relevant headers are present.
/* apply your logic on Etags */
if (null == header) {
throw new ARelevantException();
}
/* go on with the processing of the request if everything is OK */
Project project = repository.findOne(id);
/* perform some magic with your entity and your input data */
project = repository.save(project);
return project;
}
}
To handle the headers, other options are available, such as using the RequestHeader annotation. You may also give a look at RequestEntity to get the request body and header at once (just don't mix a RequestEntity parameter and #RequestBody + #RequestHeader parameters).
I'm using Jersey, I have the following method:
#POST
#Path("hello")
#Produces(MediaType.TEXT_HTML)
public String hello(#FormParam("username") String username)
{
Gson gson = new Gson();
CommunicationResponseM result = new CommunicationResponseM();
String result = "hello";
return gson.toJson(result);
}
So far all goes well, but now I need to add some headers. How can I do that?
Thanks!
PS:
I start the Jersey server in this way:
final HttpServer server = HttpServerFactory.create(baseUrl);
server.start();
You can return a Response object instead. Have a look at:
https://jersey.java.net/nonav/documentation/latest/user-guide.html#d0e5169
and
http://jersey.java.net/nonav/apidocs/1.17/jersey/javax/ws/rs/core/Response.ResponseBuilder.html
These should get you on the right track...
If you're looking for a way to get the value of a header parameter from the http request, then you can use the #HeaderParam annotation. It's similar to the #FormParam annotation.
If you're looking to add a header to your response, there are several ways.
You can inject the HttpServletResponse in your resource using the #Context annotation and call the addHeader method on it.
You can return a Response object in your method and use that to add the header. See also ResponseBuilder.
For Jersey 1, there's more info in the Jersey 1.18 user guide. See sections 2.5 and 2.13.
For the Jersey 2 user guide, see chapter 3 and section 3.6.