ERROR: Could not find message body reader - spring

I have the following error code 415 when trying to upload an image to my database and following error message:
RESTEASY003200: Could not find message body reader for type: interface org.springframework.web.multipart.MultipartFile of content type: multipart/form-data;
I believe something about my controller is wrongly setup.
My controller:
#PreAuthorize("hasAnyRole('ROLE_MANAGER', 'ROLE_ADMIN')")
#Path("upload/image/{DDSEmployeeId}")
public Response saveImage(#RequestBody MultipartFile file, #PathParam("DDSEmployeeId") String DDSEmployeeId){
System.out.println(file.getOriginalFilename());
System.out.println(DDSEmployeeId);
return doReturn(personService.saveImage(file, DDSEmployeeId));
}
My Front-End Axios call:
async sendImage ({ test }, file) {
console.log('file', file.values().next());
if (file == null) {
logError('sendImage failed');
} else {
try {
const response = await defaultAxiosClient.post(`people/upload/image/${this.selectedPerson.ddsemployeeId}`, file);
console.log(response);
} catch (exception) {
logError('sendImage failed', exception);
}
}
}
What am I doing wrong?

Related

How to return catchable error to the ajax call in Struts 2?

I have some Struts 2 actions called by Ajax. I try to deal with error and catch the error but it doesn't work as expected.
the method ajax method:
deleteIndicateur(id) {
$.ajax({
type: "DELETE",
url:"<%=request.getContextPath()%>/mesures.ce.delete.action?id=" + id,
success: function (resp) {
alert(resp);
},
error: function (resp) {
alert(resp);
}
})
},
and this Action:
#Action(value = "ce.delete", results = {
#Result(name = "success", type = "json", params = {"root", "indicateurDictionnaire"}),
#Result(name = "error", type = "json", params = {"root", "errors"})
})
public String delete() {
Integer dicId = Integer.valueOf(this.getParameter("id"));
try {
dicBo.delete(dicId);
} catch (Exception e) {
this.errors = getText(e.getMessage());
return ERROR;
}
return SUCCESS;
}
Delete works fine but when the method has an error, the error is catch by the success function in the ajax request. How I must do to return a catchable error to the Ajax?
The callback error is called if the response has a status code corresponding to the error. See the list of HTTP status codes.
To return a response with error messages and setting the status code corresponding to the error needs to configure the action result error. Similar to
#Result(name = "error", type = "json", params = {"root", "errors", "statusCode", 400})
})

Can't get data when 400 error. in Flutter

I'm trying to implement login with the Dio package in my app. When I send the correct email and password I get a 200 status code and user data. But when I send the email or password incorrect backend sends 400 error code and data like this {"message": "User Not Exist","data": [],"status": false} the problem is I'm unable to get the data when I have 400 error because in dio catchError method I can get just error and stacktrace.
Future login(String username, String password) async {
try {
String url = "$baseUrl/admin/user/login";
print(url);
var res = await dio.post(
url,
data: {"email": username, "password": password},
);
if (res.statusCode == 400) {
print(res.data); <----- This dont print anything.
return false;
} else {
print(res.data);
return true;
}
// await Future.delayed(Duration(seconds: 4));
} catch (e, s) {<----- here I have just error and stacktrace not the data
print("stacktrace $s");
print("error $e");
}
}
I solved this issue using on DioError catch instead of the catch method.
Future login(String username, String password) async {
try {
String url = "$baseUrl/admin/user/login";
print(url);
var res = await dio.post(
url,
data: {"email": username, "password": password},
);
if (res.statusCode == 400) {
print(res.data); <----- This dont print anything.
return false;
} else {
print(res.data);
return true;
}
// await Future.delayed(Duration(seconds: 4));
} on DioError catch (e) {
print(e.response.data);<-----------here I can get the data
return e.response.data;
}
}
Take try..catch out and use this form:
dio.post(...).then((response) {...}).catch(...)
Then you can use response as you wish.
You can read this article

I'm getting "Unauthenticated" message with a valid token in Laravel Passport using Flutter

I built a Web Service using Laravel Passport for authentication, when I register a user, it generates an access token successfully, but when I am trying to retrieve the user info, I get unauthenticated.
The interesting part is that making the social sign up with Postman, the access token generated works, but when I make the sign up with the app, the access token is not valid.
This is my request code on my mobile app:
Future<Map> socialSignIn(UserSocialAuth userSocialAuth) async {
final String _socialPath = '/social_auth';
Future<Map> socialSignInResponse;
try {
socialSignInResponse = postRequest(_socialPath, userSocialAuth.toJson());
} catch (error, stackTrace) {
print("Exception ocurred: $error stackTrace: $stackTrace");
socialSignInResponse = jsonDecode('{"exception": $error, "stackTrace": $stackTrace}');
}
return socialSignInResponse;
}
/// POST Request
Future<Map> postRequest(String serviceName, Map data) async {
Map responseData = {};
FormData formData = FormData.fromMap(data);
_dio.options.connectTimeout = connectTimeout;
_dio.options.receiveTimeout = receiveTimeout;
try {
Response response = await _dio.post(
_endpoint + '$serviceName',
data: formData,
options: Options(
headers: {
'Authorization': await getAccessToken(),
'Accept': 'application/json'
}
)
);
if (response.statusCode == 200) {
responseData = response.data;
}
} catch (e) {
// An error was received
responseData = {
'error': 'No se pudo conectar con el servidor de $_appName',
'exception': e.toString()
};
}
return responseData;
}
And this is the request for the user data using access token:
Future<Map> currentUser(String accessToken) async {
final String _currentUserPath = '/user';
Future<Map> userDataResponse;
try {
userDataResponse = getRequest(_currentUserPath);
} catch (error, stackTrace) {
print("Exception ocurred: $error stackTrace: $stackTrace");
userDataResponse = jsonDecode('{"exception": $error, "stackTrace": $stackTrace}');
}
return userDataResponse;
}
/// GET Request
Future<Map> getRequest(String serviceName) async {
Map responseData = {};
_dio.options.connectTimeout = connectTimeout;
_dio.options.receiveTimeout = receiveTimeout;
try {
Response response = await _dio.get(
_endpoint + '$serviceName',
options: Options(
headers: {
'Authorization': await getAccessToken(),
'Accept': 'application/json'
}
));
if (response.statusCode == 200) {
responseData = response.data;
}
} catch (e) {
// An error was received
responseData = {
'error': 'No se pudo conectar con el servidor de $_appName',
'exception': e.toString()
};
}
return responseData;
}
I do not know why works with postman and not with the app.
I save the access token with SharedPreferences like this:
/// ----------------------------------------------------------
/// Method that returns the token from Shared Preferences
/// ----------------------------------------------------------
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
Future<String> getAccessToken() async {
final SharedPreferences prefs = await _prefs;
String _authorizationToken;
if (prefs.getString(_accessTokenKey) != null) {
_authorizationToken = 'Bearer ' + prefs.getString(_accessTokenKey);
}
return _authorizationToken;
}
/// ----------------------------------------------------------
/// Method that saves the token in Shared Preferences
/// ----------------------------------------------------------
Future<bool> setAccessToken(String token) async {
final SharedPreferences prefs = await _prefs;
return prefs.setString(_accessTokenKey, token);
}

Sending file object to Spring Rest controller through angular 5

I am trying to upload a file on client side and send HTTP Post request to Spring Rest Controller. But when I receive the file object in Rest controller I could see it as 'null'.
HTML code :
<input type="file" id="myFile" (change) = "onFileChange($event)" #fileInput>
Corresponding .ts file :
onFileChange($event) : void {
let file:File = $event.target.files[0];
let myReader: FileReader = new FileReader();
myReader.onloadend = function(e) {
}
myReader.readAsText(file);
const req = this.http.post('/abc',myReader.result, {
headers: new HttpHeaders().set('content-type','application/pdf')
});
req.subscribe(
(data) => {
console.log(data);
},
(err: HttpErrorResponse) => {
if(err.error instanceof Error) {
//client side error
console.log('An error occured: ',err.error.message);
} else {
console.log('Backend returned code', err.status, 'body was ',err.error);
}
}
)
}
My Spring Rest Controller :
#RequestMapping(value="/abc", method = RequestMethod.POST, consumes = "application/pdf")
public ResponseEntity<String> uploadFile(#RequestBody MultipartFile file) {
System.out.println("Inside Controller");
return new ResponseEntity<>("true", HttpStatus.CREATED);
}
Could anyone please help to find out the issue here.
Try below code
HTML Template
<input type="file" id="myFile" (change)="onFileChange(fileInput.files)" #fileInput>
TypeScript
import { Headers, RequestOptions } from '#angular/http'; // Import header and requestOptions
//On File Select
onFileChange(files: any) {
let file: File = files[0];
let headers = new Headers();
let options = new RequestOptions({ headers: headers }); // Create header
let formData = new FormData();
formData.append('file', file); // Append file to formdata
const req = this.http.post('/abc', formData, options);
req.subscribe( (data) => {
console.log(data); // Sucess response
}, (err: HttpErrorResponse) => {
// Erro response
if(err.error instanceof Error) {
//client side error
console.log('An error occured: ',err.error.message);
}
else {
console.log('Backend returned code', err.status, 'body was ',err.error);
}
})
}
Spring Controller
#RequestMapping(value="/abc", method = RequestMethod.POST)
public ResponseGenerator uploadFile(#RequestParam MultipartFile file) {
ResponseGenerator responseGenerator = new ResponseGenerator();
try {
if (file != null) {
System.out.println(file.getOriginalFilename());
}
return responseGenerator;
} catch (Exception e) {
logger.error("Error while updating user : ", e);
return responseGenerator;
}
}
It will be better way if you create one service and put your http method code in that service. refer this link Angular 2 template form with input type=file and spring boot
the easiest thing to do (according to me) is to use a FormData object.
Here is how :
#viewChild() fileInput: ElementRef;
onFileChange(event) {
const files = this.fileInput.nativeElement.files as FileList;
const file = files.item(0);
const formData = new FormData();
formData.append('pdf', file, file.name);
this.http.post('abc', formData, {
headers: new HttpHeaders().set('content-type','application/pdf')
}).subscribe(
data => console.log(data),
err => console.log(err)
);
}
Try this and tell me what you see on Spring side.

How can I get the actual error from fetch api

I am making a fetch api call but in case of a 500 error the following middleware kicks in and sends back a json object in response body.
app.Use(async (context, next) =>
{
try
{
await next();
}
catch (Exception ex)
{
if (context.Response.HasStarted)
{
throw;
}
context.Response.StatusCode = 500;
context.Response.ContentType = "application/json";
var json = JToken.FromObject(ex);
await context.Response.WriteAsync(json.ToString());
}
});
On the client side I have the following code
return fetch(url, content)
.then(function(res) {
if (!res.ok) {
console.log(res, res.json())
throw Error(res.statusText);
}
return res;
})
.then(res => res.json())
.catch(e => console.log('Error fetching accounts:', e))
I am not able to access the json with error information. How can I do it ?
Working code after following the correct answer
return fetch(url, content)
.then(function(response) {
if (!response.ok) {
return response.json()
.then(function(obj) {
throw Error(obj.ErrorMessage)
})
}
else {
return response.json()
.then(json => {
/*further processing */
})
}
}).catch(/* work with the error */)
The json function of the Response object returns a Promise, not the actual parsed value.
res.json()
.then(function(object) {
// Here you have the parsed JSON object.
console.log(object);
});

Resources