How to fix "HttpMessageNotReadableException: Required request body is missing"? - json

I'm integrating Angular with Spring boot for basic CRUD application with login module.
Login module is working fine, whereas, for creation method I get: "HttpMessageNotReadableException: Required request body is missing" for that particular method.
This is for a basic login and CRUD operation app with angular 7 and spring boot.
arrNewUser: any[] = [];
url = 'http://localhost:8080/api/user-management/add';
constructor(private http: HttpClient, private router: Router) { }
private options = { headers: new HttpHeaders().set('Content-Type', 'application/json') };
createUser(form: NgForm) {
this.arrNewUser = form.value;
console.log('array', this.arrNewUser);
console.log('value', form.value);
this.http.post(this.url, JSON.stringify(this.arrNewUser), this.options).subscribe((res: Response) => {
console.log('Response:--', res.status);
console.log(this.router.url);
});
}
#RestController
#RequestMapping(path="/api", method = {RequestMethod.GET, RequestMethod.POST})
#CrossOrigin(origins="http://localhost:4200")
public class ControllerClass {
#PostMapping(path="/user-management/add", produces = { MediaType.APPLICATION_JSON_UTF8_VALUE })
public Status addUsers(#RequestBody String data) {
.......
return status;
}
I'm able to get required output thru postman and thru localhost:4200 angular port, but not from localhost:8080 i.e., spring boot address.

Related

java angularjs spring file upload

I am trying to upload a file to a server using angularjs and Spring (to Amazon AWS).
I checked a couple of posts on uploading with the first one and the latter but I still can't get the both to work together.
File Upload using AngularJS
How to upload a file with AngularJS?
Checked also youtube for tutorials, found Black Cloud, Brent Aureli's channel and I just cannot figure it out.
You have to be authenticated in my webapp to send post requests, but I am getting errors also when I'm logged in.
Would be extremely grateful for some help.
This is my html form:
<form>
<input type="file" file-model="file">
<button ng-click="submit()" type="submit">Click</button>
</form>
Directive for the file-model:
.directive('fileModel', ['$parse', function($parse){
return {
restrict: 'A',
link: function(scope, element,attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function() {
scope.$apply(function() {
modelSetter(scope, element[0].files[0]);
})
})
}
}
}])
Controller:
.controller('UploadController', ['$scope', 'multipartForm', function($scope, multipartForm) {
$scope.file = {};
$scope.submit = function() {
var uploadUrl = '/uploadtest';
multipartForm.post(uploadUrl, $scope.file);
}
}])
Service for multipartForm:
.service('multipartForm', ['$http', function($http){
this.post = function(uploadUrl, data) {
var fd = new FormData();
for(var key in data) {
fd.append(key, data[key]);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
}
}])
Spring Endpoint:
#RestController
#RequestMapping("/storage/")
public class BucketController {
private AmazonClient amazonClient;
#Autowired
public BucketController(AmazonClient amazonClient) {
this.amazonClient = amazonClient;
}
#RequestMapping(value = "/uploadtest", method = RequestMethod.POST)
public String uploadFile(#RequestParam(value = "file") MultipartFile file) {
System.out.println("Uploading file!!!!!!!!!!!!");
return this.amazonClient.uploadFile(file);
}
}
Error that I'm getting in the browser:
angular.js:15018 Possibly unhandled rejection:
{"data":{"timestamp":1537033312586,"status":400,"error":"Bad Request","exception":"org.springframework.web.multipart.support.MissingServletRequestPartException","message":"Required request part 'file' is not present","path":"/uploadtest"},
"status":400,
"config":{"method":"POST","transformResponse":[null],
"jsonpCallbackParam":"callback",
"headers":{"Accept":"application/json,
text/plain, /",
"X-Requested-With":"XMLHttpRequest",
"Authorization":
"Basic c3p5bW9uc3R1c3pla0BnbWFpbC5jb206dGVzdA==",
"X-XSRF-TOKEN":"395d1e27-a6ee-4948-b673-39d31902e1ae"},
"url":"/uploadtest","data":{}},
"statusText":"","xhrStatus":"complete"}
The exception occurred due the missing query param 'file' which is not presented.
And in spring endpoint you should not receive a file request in Request param!
#RequestMapping(value="/uploadtest", consumes = "multipart/form-data",method = RequestMethod.POST, produces = "application/json")
public String uploadFile(MultipartHttpServletRequest request) throws Exception{
try {
MultipartFile multipartFile1 = request.getFile("file");
if (multipartFile1 != null) {
String file1 = multipartFile1.getOriginalFilename();
InputStream inputStream = multipartFile1.getInputStream();
// do whatever
}
} catch (IOException e) {
logger.error(e.getMessage());
}
return null;
}
And in Service for multipartForm change the headers content-type to : multipart/form-data
Hope this would Help!!

Post upload files in angular 4 from spring boot?

I have an api handle the request to upload file (in spring boot) as follows:
#PostMapping("/api/admin/product/{id}/upload")
public ResponseEntity<Product> postUpload(#PathVariable("id") Integer id, #RequestParam("image") MultipartFile imageFile) {
Product product = productService.findOne(id);
return new ResponseEntity<>(productService.upload(product, imageFile),HttpStatus.OK);
}
Below is a service to process my requests. How should I fix it to fit the above api?
#Injectable()
export class ProductServiceService {
private baseUrl = 'http://localhost:8080/api/admin/product';
private headers = new Headers({'Content-Type' : 'multipart/form-data', 'Access-Control-Allow-Origin' : '*'});
private options = new RequestOptions({headers: this.headers});
constructor(private _http: Http) { }
postUpload(id) {
const formdata: FormData = new FormData();
formdata.append('image', image);
return this._http.post(this.baseUrl + '/' + id + '/upload', formdata, this.options)
.map((res: Response) => res.json())
.catch(this.errorHandler);
}
errorHandler(error: Response) {
return Observable.throw(error || 'SERVER ERROR');
}
}
And this is the error after build
Thanks!
Few of my observations based on the code shared by you:
private headers = new Headers({'Content-Type' : 'application/json'});. This is wrong, Content type should be multipart/form-data
this._http.get - this should be POST
File should be associated by image request param
I am not familiar with Angular to give you an exact answer.
Update:
If your client application is another Spring Boot application then you can run Zuul proxy on your Angular JS app and map /api URL to http://localhost:8080/api. Enabling Zuul Proxy is as simple as
* Adding dependency on spring-cloud-starter-zuul in your pom
* annotating the configuration class with #EnableZuulProxy
* Adding following in the properties: zuul.routes.api.url http://localhost:8080/api
So from your client app you call the api: http://localhost:4200/api/admin/product/17/upload and your client app (using Zuul proxy) will invoke the http://localhost:8080/api/admin/product/17/upload at the server.

HTTP Native Plugin (IONIC 3)

I'm trying to make a post request using the HTTP cordova plugin. However, for some reason, the JSON data consumed by the Server side is not being formatted correctly (json brakets). Could anyone help me please?
The import:
import { HTTP } from '#ionic-native/http';
The request implementation:
public sendData(sufix, json) {
return new Promise((resolve, reject) => {
this.http.post(URL+sufix, JSON.stringify(json), {'Content-Type': 'application/json'}).then(result => {
resolve(result.data);
}).catch(error => {
reject(error);
});
});
}
The json sended:
{name: 'Test'}
The content received by the server:
=%7B%22name%22%3A%22Test%22%7D
The server implementation:
#Path("/register")
public class RegisterEndPoint {
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response registerUser(UserDTO userDTO) {
// Create DAO for persistence
FactoryDAO factory = new FactoryDAO();
UserDAO userDAO = factory.getUserDAO();
// Create user to be persisted
if (!userDAO.userExist(userDTO.getEmail())) {
User user = new User();
user.setPassword(userDTO.getPassword());
user.setEmail(userDTO.getEmail());
user.setName(userDTO.getName());
userDAO.persist(user);
userDAO.commit();
return Response.status(200).build();
}
return Response.status(405).entity(new ErrorDTO("User already registered!")).build();
}
}
The problem seems to be in Native Plugin, so I've changed to the angular http solution, and it works fine. Follow below the solution which I've perform. Thanks everyone who helped me.
The imports required:
import { Http, Headers, RequestOptions, Response } from '#angular/http';
import { Observable } from 'rxjs/Rx'
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/timeout';
AuthProvider:
public sendRequest(sufix, json) {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(URL+sufix, json, options)
.timeout(TIMEOUT_REQUEST*1000)
.do(this.logResponse)
.map(this.extractData)
.catch(this.handleError)
}
private logResponse(res: Response) {
console.log(res);
}
private extractData(res: Response) {
return res.json();
}
private handleError(res: Response | any) {
return Observable.throw(res.json().error || 'Fail to connect to the server');
}
Calling the AuthProvider:
this.authProvider.sendRequest('register', this.signup).subscribe((data) => {
console.log('Success!');
}, (error) => {
console.log(error);
});
Providers included in app.module.ts
import { HttpModule, JsonpModule } from '#angular/http';
can you please try sending the body without making it a string. you can send the JSON Object without stringify. Give it a try :)
**UPDATE
After sending this
{name: 'Test'}
If you are getting name = "test"
Why dont you try like this
var data = JSON.stringify(data);
var obj = {data:data};
//send the obj Object
So it will show as data = "{name:test}"
Now Parse it from the server. Try and let me know :)
if you are trying to make post request using HTTP then try sending request in this format.
let body = new FormData();
body.append('name', 'Test');
this.http.post(<url>,body);
Try and lemme know if it works for you.
Just add this.http.setDataSerializer(‘json’) before do the post

How am i supposed to use a Auth0 with a RESTful api?

I'm thinking about using Auth0 to signin my users on my nodejs API.
I'm using a MySQL database to sign them in and i also want to use Facebook so they can register and login.
I'm having an issue with the concept of callback, because my API is not supposed to be accessed via a browser. Only a webapp or a mobile app is supposed to access it. How do i have to implement the handling of my signin/login form inputs on my mobile app to use my API which is supposed to use Auth0 ?
Thank you for your answers.
Auth0 comes with a database on the free account. When you add the login registration widget to your application and a user signs up it adds them to the database in your auth0 account.
You can see information about the process here
What I do is authenticate users with the auth0 widget. This allows auth0 to handle encryption and security. Then when a user logs in i request a profile in the response. Typically this gives me at least basic info like an email address. I create my own database using the email address as a unique key which allows me to serve the correct data to the user when they login.
Here is an example of my auth0 service using a widget and requesting the user's profile in the response then storing it to local storage.
import { Injectable } from '#angular/core';
import { tokenNotExpired, JwtHelper } from 'angular2-jwt';
import { Router } from '#angular/router';
import { myConfig } from './auth.config';
declare var Auth0Lock: any;
var options = {
theme: {
logo: '/img/logo.png',
primaryColor: '#779476'
},
languageDictionary: {
emailInputPlaceholder: "email#example.com",
title: "Login or SignUp"
},
};
#Injectable()
export class Auth {
lock = new Auth0Lock(myConfig.clientID, myConfig.domain, options, {});
userProfile: Object;
constructor(private router: Router) {
this.userProfile = JSON.parse(localStorage.getItem('profile'));
this.lock.on('authenticated', (authResult: any) => {
localStorage.setItem('access_token', authResult.idToken);
this.lock.getProfile(authResult.idToken, (error: any, profile: any) => {
if (error) {
console.log(error);
return;
}
localStorage.setItem('profile', JSON.stringify(profile));
this.userProfile = profile;
this.router.navigateByUrl('/overview');
});
this.lock.hide();
});
}
public login() {
this.lock.show();
}
private get accessToken(): string {
return localStorage.getItem('access_token');
}
public authenticated(): boolean {
try {
var jwtHelper: JwtHelper = new JwtHelper();
var token = this.accessToken;
if (jwtHelper.isTokenExpired(token))
return false;
return true;
}
catch (err) {
return false;
}
}
public logout() {
localStorage.removeItem('profile');
localStorage.removeItem('access_token');
this.userProfile = undefined;
this.router.navigateByUrl('/home');
};
}

use angular 2 data from rest api

I'm begining in Angular 2 , in the first I try to get data from JSON file and show it on a table and that's done , now I want to get data from rest api so I create my Restful webservices from Entity classes , I generate the CrossOriginResourceSharingFilter ( I use netbeans and glassfish) and I get the link with JSON output , I replace the link in the api url in angular 2 but it doesn't work
this in my Angular 2 employes.service
#Injectable()
export class EmployesService {
private empsUrl = 'localhost:25176/WebApplication4/app/employes'; // URL to web api
constructor(private http: Http) { }
getEmployes (){
return this.http.get(this.empUrl)
.map(res=> res.json())
.catch(this.handleError);
}
this is my employes.component
export class EmployesComponent implements OnInit{
emps: Employe[];
error: any;
mode = 'Observable';
errorMessage :string;
constructor(private empService: EmployesService,private _elRef :ElementRef) { }
getEmployes() {
this.empService.getEmployes()
.subscribe(
employes => this.emps = employes,
error => this.errorMessage = <any>error);
}
ngOnInit() {
this.getEmployes();
this is my console Errors
zone.js:101 XMLHttpRequest cannot load localhost:25176/WebApplication4/app/employes. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.
thank you for helping