Trying to pass Json object to Jersey restfull service as FormDataParam - java

I do not know how to pass Java object to Jersey restfull service as FormDataParam. The service works perfectly with curl, but Swagger responds with error. The problem is most probably with annotation #FormDataParam. Swagger does not throw 415 Error Unsupported Media File, but it
Here is the code Jersey service:
#POST
#ApiOperation(value = "Upload", notes = "", response = ImageAPIResponse.class)
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, "application/x-javascript" })
#Consumes(MediaType.MULTIPART_FORM_DATA)
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Successful or application error (see notes)", response = ImageAPIResponse.class) })
public ImageAPIUploadUpdateResponse upload(
#ApiParam(required = true, value = "user name part of credentials") #FormDataParam("user_name") String userName, //
#ApiParam(required = true, value = "") #FormDataParam("file") File file, //
#ApiParam(required = true, value = "") #FormDataParam("file") FormDataContentDisposition contentDispositionHeader,
#ApiParam(required = false, value = "") #FormDataParam("file_name") String fileName,
#ApiParam(required = false, value = "") #FormDataParam("meta_data") ImageMetaData metaData) {
ImageAPIResponse imageAPIResponse = new ImageAPIResponse();
//metaData object keeps being null...
return imageAPIResponse;
}
public class ImageMetaData{
public String fileName;
public String fileType;
}
Did anyone encounter a similar problem with FormDataParam? It would be great if I could use this Jersey annotation in my parameters.

Related

What is the correct way of testing a POST endpoint that accepts a POJO and a MultipartFile[] attachment?

I'm new to MockMVC. I've successfully written some basic tests, but I got stuck on trying to test an use case with the endpoint that requires a POST request with two parameters - a POJO and an array of MultipartFile. The test is written as such:
#Test
public void vytvorPodnetTest() throws Exception {
var somePojo = new SomePojo();
somePojo.setSomeVariable("test_value");
var roles = List.of("TEST_USER");
var uid = "00000000-0000-0000-0000-000000000001";
MockMultipartFile[] attachments = {new MockMultipartFile("file1.txt", "file1.txt", "text/plain", "file1 content".getBytes()),
new MockMultipartFile("file2.txt", "file2.txt", "text/plain", "file2 content".getBytes())};
MockMultipartHttpServletRequestBuilder builder = MockMvcRequestBuilders.multipart("/some-pojo/create");
builder.with(req - {
req.setMethod("POST");
return req;
});
MvcResult result = mockMvc.perform(builder.file(attachments[0]).file(attachments[1])
.param("SomePojo", new ObjectMapper().writeValueAsString(somePojo))
.file(attachment[0])
.with(TestUtils.generateJWTToken(uid, roles)))
.andExpect(status.isOk())
.andReturn();
}
The controller method is as follows:
#PostMapping(value = "/create", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
public UUID createPojo(
#RequestPart(value = "SomePojo") SomePojo somePojo,
#RequestPart(value = "attachments", required = false) MultipartFile[] attachments) {
return pojoService.create(somePojo, attachments);
}
It stops here, before reaching the service. I've tried adding the files both as a param "attachments" and like shown above, but all I get is "400 Bad Request"
Finally found the way to send the parameters as MockMultipartFile from MockMVC to the controller:
MockMultipartFile pojoJson = new MockMultipartFile("SomePojo", null,
"application/json", JsonUtils.toJSON(podnet).getBytes());
mockMvc.perform(MockMvcRequestBuilders.multipart("/some-pojo/create")
.file(pojoJson)
.contentType(MediaType.MULTIPART_FORM_DATA_VALUE)
.with(new TestUtils().generateJWTToken(uid, roles)))
.andExpect(status().isOk()).andReturn().getResponse().getContentAsString();

Why cannot find the response part in swagger api request? 404 error / this is the jsp project

I built a dummy api and I want to test it on swagger. The swagger.json has been successfully generated and executed to show the swagger UI.
But there is the 404 error that cannot find the response part.
How can I solve this?
This is the built swagger UI.
And this is the code.
#Service
#Api
public class className () {
#GET
#Path("/oauth2/authorize")
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
#ApiOperation(value = "Authorization Grant", notes = "Authorization Grant")
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Successfully Granted the Authorization"),
#ApiResponse(code = 400, message = "Missing or invalid request body"),
#ApiResponse(code = 403, message = "Forbidden"),
#ApiResponse(code = 404, message = "Schema not found"),
#ApiResponse(code = 500, message = "Internal error")})
public Response authorizationGrant(
#HeaderParam("X-AUTH-TOKEN") final String token,
#HeaderParam("X-CSRF-TOKEN") final String csrftoken,
#ApiParam(value = "Client ID", required = true) #QueryParam("Client ID") final String clientId,
#ApiParam(value = "Scope", required = true) #QueryParam("Scope") final String scope,
#ApiParam(value = "Redirect Uri", required = true) #QueryParam("Redirect Uri") final String redirectUri,
#ApiParam(value = "Response Type", required = true) #QueryParam("Response Type") final String responseType ) throws AccessDeniedException {
return Response
.status(Response.Status.OK)
.entity("{\"hello\": \"This is a JSON response\"}")
.type(MediaType.APPLICATION_JSON)
.build();
}
}
Please tell me what you need more to be clear with this error.
The problem solved!!!
I hope this answer could help for others who are suffered from this trouble. :)
The error was from the #Api Definition part. I should have define the path in that part.
This is the corrected code.
#Path("/oauth2")
#Service
#Api
public class className () {
.....
#GET
#Path("/authorize")
.....
}
As you can see the #Api definition part requires the #Path annotation.
:)

Swagger datatype not generating docs

I have the below code in Swagger,
#Path("/v1")
#ApiOperation(value = "POST - Some Value", nickname = "post-funtion", consumes = "application/json", produces = "text/html; charset=UTF-8", tags = {
"Some Controller" })
#ApiImplicitParams({
#ApiImplicitParam(name = "Authorization", paramType = "header", dataType = "string", format = "JWT", required = false, value = "A User Service JWT"),
#ApiImplicitParam(name = "Request", value = "Request Object", paramType = "body", dataType = "org.pkg.SomeRequest", required = true) })
#ApiResponses({
#ApiResponse(code = 200, message = "Value Added", response = SomeResponse.class) })
private Object retrieveByName(Request request, Response response)
{
return new RetrieveByNameRqstHandler(catalogService, request, response).handle();
}
The code is supposed to automatically generate default json request depending upon the datatype which in this case is "org.pkg.SomeRequest" but there is nothing generated. On the contrary if I change the "org.pkg.SomeRequest" with "org.pkg.SomeResponse" there is a default JSON generated for this. Can anybody help me please?
Consider both classes SomeRequest,SomeResponse have the same code.
This is the image where I use "org.pkg.SomeRequest" in the dataType
This is the image where I use "org.pkg.SomeResponse" in the dataType
According to this GitHub issue on Swagger core project, if you add the annotation #ApiImplicitParam should resolve your problem.
#ApiImplicitParams({
#ApiImplicitParam(
required = true,
dataType = "com.example.SomeObjectDto",
paramType = "body"
)
})
But normally if you just add the class on your method signature it'll work.
private Object retrieveByName(SomeObjectDto someObjectDto) {
someCode();
}
Also SomeObjectDto class should contain "get" methods for your variables like.
class SomeObjectDto {
private String info;
getInfo(){
return info;
}
}
Will produce the following JSon.
{ info: "string" }
ApiImplicitParam can map a parameter to a correct type, but the type must be detected by swagger, so must be a valid reference.
The only way I could make this working is by using additionalModels method.
Example in spring-boot:
configure swagger
import springfox.documentation.spring.web.plugins.Docket;
import com.fasterxml.classmate.TypeResolver;
...
#Bean
public Docket api(TypeResolver typeResolver) {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("your-group-rest-api")
.select()
.apis(RequestHandlerSelectors.basePackage("your.package"))
.paths(PathSelectors.any())
.build()
.additionalModels(typeResolver.resolve(YourModel.class))
.apiInfo(apiInfo());
}
controller
#ApiOperation...
#ApiImplicitParams(
#ApiImplicitParam(dataType = "YourModel", name = "requestJson", paramType = "body"))
#ApiResponses...
#RequestMapping...
public void yourMethod(#RequestBody String requestJson,...)
Of course, you could have an InputStream parameter for the request and map that to your model.

How to generate file chooser in Swagger-ui for body inpustream

Hello i have the following jaxrs entry
#PUT()
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_OCTET_STREAM)
#ApiOperation(value = "Bla bla.")
#Path("secure/flappy")
public Response testput(
#ApiParam(value = "pwet",type = "file",format = "binary", required = true) InputStream certificate) throws Throwable {
try (InputStream stream = certificate) {
//Consume stream
return Response.ok().build();
}
}
And the generated swagger-ui page for this entry
I would like to know how to document my paremeter for getting only one parameter presented as a file chooser in swagger-ui.
#sdc: You're right i had to use multi part form data for getting a working file chooser in Swagger-ui. I also had to use #ApiImplicitParam for getting it working.
#PUT()
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.MULTIPART_FORM_DATA)
#ApiOperation(value = "Bla bla.")
#Path("secure/flappy")
#ApiImplicitParams({
#ApiImplicitParam(name = "file", value = "bla bla.", required = true, dataType = "java.io.File", paramType = "form")
})
public Response testput(#ApiParam(hidden = true) #FormDataParam("file") final InputStream certificate
) throws Throwable {
//TODO do something
return Response.ok().build();
}
I am not very familiar with Swagger UI, but this thread might be helpful
https://github.com/swagger-api/swagger-ui/issues/72
I see an example using an#ApiParam annotation
and this post talks about a file upload with the
def uploadFile annotation
https://github.com/swagger-api/swagger-ui/issues/169
#PUT
#Path("/secure/flappy")
#Consumes(Array(MediaType.MULTIPART_FORM_DATA))
#ApiOperation(value = "test a put file upload")
def uploadFile(
#ApiParam(value = "file to upload", required=false) #FormDataParam("file") inputStream: InputStream,
#ApiParam(value = "file detail") #FormDataParam("file") fileDetail: FormDataContentDisposition) = {
val uploadedFileLocation = "./" + fileDetail.getFileName
IOUtils.copy(inputStream, new FileOutputStream(uploadedFileLocation))
val msg = "File uploaded to " + uploadedFileLocation + ", " + (new java.io.File(uploadedFileLocation)).length + " bytes"
val output = new com.wordnik.swagger.sample.model.ApiResponse(200, msg)
Response.status(200).entity(output).build()
}
I suppose you need to use in the parameter description following:
#RequestPart("file") MultipartFile file
At least for me it gives a swagger form with a file selection button.
The solution was found in the examples here:
https://github.com/springfox/springfox-demos

How to Postman POST json body and attach file?

I have back-end API to allow user POST a json_body and with a file:
#RequestMapping(value = "/sendemail",
method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE,
consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}
)
public #ResponseBody ResponseEntity<String> sendEmailToClients(
#RequestBody String jsonData,
#RequestParam(value = "file", required = false) final MultipartFile file) {
...
}
Question: On Postman Tool, Is there any way to make a POST for sending out json_body and file upload?

Categories

Resources