IBM MobileFirst Adapter accepting Multipart request - java

I am a newbie to IBM MobileFirst, I am trying to upload an image using Multipart. Whenever I try to call the API to upload image I get an error in the Postman saying 415 content not found or 500 server error. So I just wanted to know does IBM mobile first java adapter accepts multi-part requests?
I have attached the Java code used , but none of these are working:
1)
#RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public #ResponseBody
String uploadFileHandler(#RequestParam("file") MultipartFile file)
{
return null;
}
tried this also :
#POST
#Path("/upload")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
#OAuthSecurity(enabled=false)
public ResponseEntity<?> upload(#RequestParam("files") MultipartFile files) {
log.info("XXXXXXXXXXXXXXXXXXXX");
return null;
}
#POST
#Path("/addEmployeeAttachment")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.MULTIPART_FORM_DATA)
#OAuthSecurity(enabled=false)
public #ResponseBody Map<String, Object> addEmployeeAttachment(
#RequestParam(required = false, value = "attachmentFile") MultipartFile attachmentFile) {
log.info("xxxxxxxxxx");
return null;
}

With reference to IBM Mobile first development reference document https://www.ibm.com/support/knowledgecenter/SSHS8R_8.0.0/com.ibm.worklight.apiref.doc/apiref/c_restapi_oview.html
We can use Deploy (POST) for Deploys a multipart compressed file.
JSON example:-
{
"ok" : false,
"productVersion" : "8.0",
"transaction" : {
"appServerId" : "Tomcat",
"description" : {
"name" : "myname",
"type" : "mytype",
},
"errors" : [
{
"details" : "An internal error occured.",
},
...
],
"id" : 1,
"project" : {
"name" : "myproject",
},
"status" : "FAILURE",
"timeCreated" : "2014-04-13T00:18:36.979Z",
"timeUpdated" : "2014-04-14T00:18:36.979Z",
"type" : "UPLOAD_ARTIFACT",
"userName" : "demouser",
},
}
Standard Error code:-
Errors 400 No deployable data is provided. 403 The user is not
authorized to call this service. 404 The corresponding runtime is not
found or not running. 500 An internal error occurred.
Could you pleas refer How can I make a multipart/form-data POST request using Java? as well.
I hope it will help you to understand more about multipart API.

Related

Spring Boot Unsupported Media Type (415) for file uploads

I'm trying to create a new POST endpoint using Spring Boot using the following code:
#Controller
#Path("/my")
#MultipartConfig(maxFileSize = 1024*1024*1024, maxRequestSize = 1024*1024*1024)
public class MyResource {
#POST
#Path("parseFile")
#ApiResponses(value = {
#ApiResponse(responseCode = "200", description = "OK"),
#ApiResponse(responseCode = "400", description = "Invalid format")})
})
public Response parseFile(#RequestParam("file") MultipartFile file) {
// Use file
}
}
I've added config in application.yml file:
spring:
servlet:
multipart:
enabled: true
max-file-size: 2MB
file-size-threshold: 3MB
Based on the docs here, it should automagically work and allow requests, but I'm getting the following response:
{
"timestamp": 1667463311931,
"status": 415,
"error": "Unsupported Media Type",
"path": "/app/api/my/parseFile"
}
I've also tried adding AutoConfig elements manually as well in a #Configuration class like:
#Bean
public MultipartAutoConfiguration multipartAutoConfiguration() {
var props = new MultipartProperties();
props.setMaxFileSize(DataSize.ofMegabytes(10));
props.setEnabled(true);
return new MultipartAutoConfiguration(props);
}
On the server side I'm only seeing the following log:
{"#timestamp":"2022-11-03T08:10:34.066Z","message":"0:0:0:0:0:0:0:1 - - [03/Nov/2022:08:10:34 +0000] \"POST /app/api/my/parseFile HTTP/1.1\" 415 126 \"-\" \"PostmanRuntime/7.29.2\"","request_id":"-","local_request_id":"4f9396ff817861e9","ext":{"accessLog":true,"cloudId":"fake","host":"0:0:0:0:0:0:0:1","method":"POST","protocol":"HTTP/1.1","statusCode":"415","requestedUri":"/app/api/my/parseFile","requestPath":"/app/api/my/parseFile","responseContentLength":"126","elapsedTimeMs":"5"}}
Postman Request:
The file type that I'm trying to upload is of type *.ics and is a text file.
I'm using Spring Boot version 2.5.2.
The error says that the media type header you send is not supported. I'm not 100% familiar #POST but I guess there is a possibility there as well.
In any cases, you can use Spring annotations. Change it from #POST and #Path to #PostMapping(path = "parseFile", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
change your post method to this
#PostMapping(value="/parsefile", consumes ="multipart/form-data")
public Response parseFile(#RequestParam(value = "file") MultipartFile file)
{
// Use file
}

Webhook to collect a JSON: Request method POST not supported

I'm writing a controller with Java for a webhook URL that receives a POST method call, with a JSON body, that I need to collect.
This is a simplified version of the controller, with Spring annotations:
#RestController
public class MyWebhoook {
#PostMapping("/my-webhook")
public void getMyJson(#RequestBody Map<String, Object> json) {
System.out.println("WebHook collected JSON: " + json);
}
}
I test it with Postman sending this JSON:
Header: Content-Type / application/json
{
"webhookKey" : "tranviaVermellCostaAvall",
"token" : "xx",
"channelId": 1,
"propertyId": "999999",
"status": "new",
"reservationId": "111211221",
"reservationStatus" : 1
}
And I get this answer:
{
"timestamp": "2019-04-09T07:23:38.093+0000",
"status": 405,
"error": "Method Not Allowed",
"message": "Request method 'POST' not supported",
"path": "/my-webhook"
}
The server log, gives some more information:
Request method 'POST' not supported, path=/my-webhook}] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter#7756c3cd
I've tried those different approaches, with the same result:
#RequestMapping(value = "/my-webhook", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.POST) instead of the #PostMapping("/my-webhook") annotation.
Modelling the received JSON as a java object instead of the Map<String, Object> json.
Using HttpServletRequest instead of the #RequestBody annotation, trying to read the request as a String.
I do not understand the reason why the POST method is not allowed. Any help, would be very much appreciated.
I added {} between your method and got a 200 as return. I added the pictures below on what code, request and console output i got.
I copied your code to my spring boot app, worked perfectly via postman...
API:
#PostMapping("/my-webhook")
public void getMyJson(#RequestBody Map<String, Object> json) {
System.out.println("WebHook collected JSON: " + json);
}
RequestBody:
{
"webhookKey" : "tranviaVermellCostaAvall",
"token" : "xx",
"channelId": 1,
"propertyId": "999999",
"status": "new",
"reservationId": "111211221",
"reservationStatus" : 1
}
URL: http://localhost:8080/my-webhook
Try to:
Update and Clean your project.
Invalidate IDE cache and restart it, and try again.
The problem was with the CSRF (Cross-site request forgery) security configuration. The path of the webhook, has to be taken out of the CSRF control. Otherwise, the POST request doesn't pass the CSRF control.
This is a simplified extract of the security settings:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http)throws Exception{
http
.csrf()
.ignoringAntMatchers("/my/webhook")

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.

Spring Rest Service Post request error

It may be a basic question related to Spring Rest service Post request
Below is my Controller mapping code:
#RequestMapping(value = "test", method = RequestMethod.POST)
#ResponseBody
public String addFruits(#RequestBody RequestWrapper fruits) {
// ...
System.out.println("test");
return null;
}
Below is the RequestWrapper class:
public class RequestWrapper{
List<String> ids;
String languageCode;
...
}
Now if in advanced Chrome rest client, with content-type as application/json
if I post the following request :
["ids": [{ "1","2","3","4"}]
,
"languageCode" : "en_US"
]
I get the following error:
Error 400: SRVE0295E: Error reported: 400
Any clue as to where I am going wrong?
The issue was due to an incorrect JSON format in the actual question.
With due help from Soitirios Delimanolis and Alejandro Agapito Bautista could correct the json format and the code worked.
The correct json format is:
{ "ids": [ 1, 2, 3, 4 ], "languageCode": "en_US" }
Also learnt from Alejandro Agapito Bautista's the json validation link
jsonlint.com

Http status 404 (Not Found) on jquery ajax GET to spring controller?

My spring controller contains such get handler :
#RequestMapping(value = "/country", method = RequestMethod.GET, produces = "application/json")
public #ResponseBody List<Region> getRegionsFor(#RequestParam(value = "countryName") String countryName,
#RequestParam(value = "geonameId") Long geonameId) {
logger.debug("fetching regions for {}, with geonameId {}", countryName, geonameId);
RegionInfo regionInfo = restTemplate.getForObject(
"http://api.geonames.org/childrenJSON?geonameId={geonameId}&username=geonameUser2014",
RegionInfo.class, geonameId);
return regionInfo.getRegions();
}
#Controller is mapped to /hostel. So url is /hostel/country?countryName=%27&Albania%27&&geonameId=783754
When I type in chrome browser
http://localhost:8080/HostMe/hostel/country?countryName=%27Albania%27&geonameId=783754
It returns json response as expected!!!
But I want to access this url with the following ajax call made with jquery:
$.ajax({
headers : {
'Accept' : 'application/json'
},
url : '/hostel/country',
dataType : 'json',
data : {countryName:"Albania",geonameId:783754},
type : 'GET',
async : true,
success : function(response) {
console.log("response=" + response.join(','));
},
error : function(errorData) {
console.log("data on fail ");
printObject(errorData);
}
});
As you guess this doesn't work at all. Http status 404 (Not Found) is returned to error: handler .
How can I solve this?
The url in the ajax call is relative to the hostname. You need to add your web application context
url : '/HostMe/hostel/country',

Categories