Angular4 doesn't send post data - spring

Angular HttpClient doesnt send data to controller.
I get a error 500 (because username in controller is null) when i try to execute fun().
test.sevice.ts
import { Injectable } from '#angular/core';
import {HttpClient} from "#angular/common/http";
import 'rxjs/Rx';
import { Observable } from 'rxjs/Rx';
#Injectable()
export class RestService {
private EndPointUrl = 'http://127.0.0.1:8080/api/test';
constructor(public http: HttpClient){}
fun(){
this.test().subscribe((data)=>console.log(data));
}
test(): Observable<string>{
let params = new URLSearchParams();
params.append("grant_type",'password');
params.append('username', 'Name');
let body = params.toString();
let headers = new HttpHeaders();
headers.set('Content-Type', 'application/x-www-form-urlencoded');
return this.http.post<string>(this.EndPointUrl, body);
}
}
package.json
...
"dependencies": {
"#angular/common": "4.3.4",
"#angular/compiler": "4.3.4",
"#angular/compiler-cli": "4.3.4",
"#angular/core": "4.3.4",
"#angular/forms": "4.3.4",
"#angular/http": "4.3.4",
"#angular/common/http": "4.3.4",
"#angular/platform-browser": "4.3.4",
"#angular/platform-browser-dynamic": "4.3.4",
...},
Spring MVC Controller:
#RequestMapping(value="/test",
method = RequestMethod.POST,
produces=MediaType.APPLICATION_JSON_VALUE)
public String[] test(HttpServletRequest request){
Map<String, String[]> parameters = request.getParameterMap();
return parameters.get("username");
}
Request from postMan works, and returns some username.
Does anyone know what I'm doing wrong?

What i can see is you're using HttpClient not correctly ... cause it came in angular 4.3.* and is little bit different from the old Http ..
you don't have to do anymore .json() ..so for example:
return this.http.post<string>(this.EndPointUrl, body) //<-- IT DON'T NEED HEADERS F.. ITKNOWS IT'S A application/x-www-form-urlencoded
.map((resp) => {
return resp; //<-- HERE resp is your resp.json()
})
.catch((err)=>{
console.log(err);
}); }
and then your post:
let dataForm = new URLSearchParams();
dataForm.append('userName', "MyUserName");
let body = dataForm.toString();
return this.http.post<string>(this.EndPointUrl, body) //<-- IT DON'T NEED HEADERS F.. ITKNOWS IT'S A application/x-www-form-urlencoded
.map((resp) => {
return resp; //<-- HERE resp is your resp.json()
})
.catch((err)=>{
console.log(err);
}); }

use Http instead of HttpClient:
import {Http} from '#angular/http';
...
constructor(private http: Http) { }
...

Related

problemas en mi frontend

import { HttpRequest, HttpHandler, HTTP_INTERCEPTORS } from "#angular/common/http";
import { Injectable } from "#angular/core";
import { Observable } from "rxjs";
import { TokenService } from "./token.service";
#Injectable({
providedIn: 'root'
})
export class InterceptorService {
constructor(private tokenService: TokenService) {
intercep(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>{
let intReq = req;
const token = this.tokenService.getToken();
if (token != null) {
intReq = req.clone({
headers: req.headers.set('Authorization','Bearer'+token)
});
}
return next.handle(intReq);
}
}
export const interceptorProvider =[{
provide: HTTP_INTERCEPTORS,
useClass: InterceptorService,
multi: true
}];
//No reconoce y marca error en interceptor, req, token, next //todos errores no reconoce ni me dice de importar nada //

Angular, error 500 after sending the request in the header

I have a hard time passing the right angular request to the header. This is my service:
import { Injectable } from '#angular/core';
import { HttpClient, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpHeaders }
from '#angular/common/http';
import { Utente } from '../model/Utente ';
import { Prodotto } from '../model/Prodotto ';
import { OktaAuthService } from '#okta/okta-angular';
import { Observable, from } from 'rxjs';
import { Carrello } from '../model/Carrello ';
import { userInfo } from 'node:os';
import { getLocaleCurrencyCode } from '#angular/common';
const headers = new HttpHeaders().set('Accept', 'application/json');
#Injectable({
providedIn: 'root'
})
export class HttpClientService {
constructor(
private httpClient:HttpClient, private oktaAuth:OktaAuthService ) {}
getCarr(){
return this.httpClient.get<Carrello[]>('http://localhost:8080/prodotti/utente/vedicarrelloo', {headers} );
}
}
This is my spring method:
#Transactional(readOnly = true)
public List<Carrello> getCarrello(#AuthenticationPrincipal OidcUser utente){
Utente u= utenteRepository.findByEmail(utente.getEmail());
return carrelloRepository.findByUtente(u);
}
In console I get this error (error 500):
https://i.stack.imgur.com/BiONS.png
this error corresponds in my console to "java.lang.NullPointerException: null.
But if I access localhost: 8080, I can see the answer correctly, so I assume there is a problem in passing the request header in angular, can anyone tell me where am I wrong, please? I specify that I get this error only in the methods where the OidcUser is present, the rest works perfectly. Thank you!
You need to send an access token with your request. Like this:
import { Component, OnInit } from '#angular/core';
import { OktaAuthService } from '#okta/okta-angular';
import { HttpClient } from '#angular/common/http';
import sampleConfig from '../app.config';
interface Message {
date: string;
text: string;
}
#Component({
selector: 'app-messages',
templateUrl: './messages.component.html',
styleUrls: ['./messages.component.css']
})
export class MessagesComponent implements OnInit {
failed: Boolean;
messages: Array<Message> [];
constructor(public oktaAuth: OktaAuthService, private http: HttpClient) {
this.messages = [];
}
async ngOnInit() {
const accessToken = await this.oktaAuth.getAccessToken();
this.http.get(sampleConfig.resourceServer.messagesUrl, {
headers: {
Authorization: 'Bearer ' + accessToken,
}
}).subscribe((data: any) => {
let index = 1;
const messages = data.messages.map((message) => {
const date = new Date(message.date);
const day = date.toLocaleDateString();
const time = date.toLocaleTimeString();
return {
date: `${day} ${time}`,
text: message.text,
index: index++
};
});
[].push.apply(this.messages, messages);
}, (err) => {
console.error(err);
this.failed = true;
});
}
}
On the Spring side, if you want it to accept a JWT, you'll need to change to use Jwt instead of OidcUser. Example here.
#GetMapping("/")
public String index(#AuthenticationPrincipal Jwt jwt) {
return String.format("Hello, %s!", jwt.getSubject());
}

Could not find acceptable representation for file download

I want to implement file download using this Angular 6 code:
Rest API:
private static final Logger LOG = LoggerFactory.getLogger(DownloadsController.class);
private static final String EXTERNAL_FILE_PATH = "/Users/test/Documents/blacklist_api.pdf";
#GetMapping("export")
public ResponseEntity<FileInputStream> export() throws IOException {
File pdfFile = Paths.get(EXTERNAL_FILE_PATH).toFile();
HttpHeaders headers = new HttpHeaders();
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
return ResponseEntity.ok().headers(headers).contentLength(pdfFile.length())
.contentType(MediaType.parseMediaType("application/pdf"))
.body(new FileInputStream(pdfFile));
}
Service:
import {Injectable} from '#angular/core';
import {HttpClient, HttpParams} from "#angular/common/http";
import {Observable} from "rxjs/index";
import {environment} from "../../../environments/environment";
import {HttpUtils} from "../common/http-utils";
import { map } from 'rxjs/operators';
import {Http, ResponseContentType} from '#angular/http';
#Injectable({
providedIn: 'root'
})
export class DownloadService {
constructor(private http: HttpClient) {
}
downloadPDF(): any {
return this.http.get(environment.api.urls.downloads.getPdf, {
responseType: 'blob'
})
.pipe(
map((res: any) => {
return new Blob([res.blob()], {
type: 'application/pdf'
})
})
);
}
}
Component:
import {Component, OnInit} from '#angular/core';
import {DownloadService} from "../service/download.service";
import {ActivatedRoute, Router} from "#angular/router";
import {flatMap} from "rxjs/internal/operators";
import {of} from "rxjs/index";
import { map } from 'rxjs/operators';
#Component({
selector: 'app-download',
templateUrl: './download.component.html',
styleUrls: ['./download.component.scss']
})
export class DownloadComponent implements OnInit {
constructor(private downloadService: DownloadService,
private router: Router,
private route: ActivatedRoute) {
}
ngOnInit() {
}
export() {
this.downloadService.downloadPDF().subscribe(res => {
const fileURL = URL.createObjectURL(res);
window.open(fileURL, '_blank');
});
}
}
The file is present in the directory but when I try to download it I get error:
18:35:25,032 WARN [org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver] (default task-2) Resolved [org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation]
Do you know how I can fix this issue?
Do I need to add additional configuration in order to download the file via Angular web UI?
I use spring-boot-starter-parent version 2.1.0.RELEASE
FileSaver npmjs.com/package/ngx-filesaver is the best library for file download in Angular6 but it has various issues in ios devices. We fixed it by writing own methods and conditionally handling it .
Component
download() {
this.downloadService.downloadPDF().subscribe(async (res: Blob) => {
if (this.isIOSMobileDevice) {
const file = new File([res], fileName, { type: 'application/pdf' });
const dataStringURL: any = await this.fileService.readFile(file);
this.hrefLink = this.sanitizer.bypassSecurityTrustUrl(dataStringURL);
} else {
saveFile(res, fileName);
}
});
}
export const saveFile = (blobContent: Blob, fileName) => {
const isIOS = (!!navigator.platform.match(/iPhone|iPod|iPad/)) || (navigator.userAgent.match(/Mac/) && navigator.maxTouchPoints && navigator.maxTouchPoints > 2);
const blob = new Blob([blobContent], { type: 'application/pdf' });
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, fileName);
} else {
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
document.body.appendChild(link);
link.href = url;
link.target = '_self';
link.download = fileName;
link.click();
document.body.removeChild(link);
}
};
File Service
async readFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
resolve(reader.result);
};
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
HTML code
<a *ngIf="isIOSMobileDevice" [href]="hrefLink"
target="_blank">Download</a>
<a *ngIf="!isIOSMobileDevice" href="javascript:;" (click)="download"
target="_blank">Download</a>
For ios Mobile devices ,download method has to be called in prerequisite so that we get hrefLink.

The specified content type was not found - Error 611 - NativeScript

I'm following the step by step tutorial of NativeScript but I'm facing the following issue:
When I try to make a post request through my Angular service I get the following error:
JS: {"message":"The specified content type was not found.","errorCode":611}
My code looks pretty much the same as the one in the official docs from NativeScript:
import { Injectable } from '#angular/core';
import { Http, Headers, Response } from '#angular/http';
import { User } from './user';
import { Config } from '../config';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
#Injectable()
export class UserService {
constructor(private _http: Http) { }
register(user: User): Observable<Response> {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
const url = `${Config.apiUrl}/Users`;
const body = JSON.stringify({
Username: user.email,
Email: user.email,
Password: user.password
});
return this._http.post(url, body, { headers })
.catch(this.handleErrors);
}
handleErrors(error: Response) {
console.error(JSON.stringify(error.json()));
return Observable.throw(error);
}
}
Component class:
signUp() {
this._user.register(this.user).subscribe(
() => {
alert('Your account has been successfully created.');
this.toggleDisplay();
},
() => {
// errors here...
alert('Unfortunately we were unable to create your account.');
}
);
}
Tested under Android and IOs, both throws the same error.
Isn't application/json the expected Content-Type in this case?
If I change the type I get another error saying that the type is missing or is invalid.
Can someone please point out what am I missing?

How to create authentication in Angular 2 with Laravel Passport?

I have a problem to find way to make authentication for my angular 2 app. I have API in laravel, and tried to use laravel passport(via password grant). I tested it on Postman and now I need to connect it with angular. I've started looking for some library to do it, but i find only this https://github.com/manfredsteyer/angular-oauth2-oidc
Do you have any ideas on how to connect this? I can not cope with that.
You can make service like this , don't forget to assign the client id and secret.
userservice.ts
import {Injectable} from '#angular/core';
import {Observable} from 'rxjs/Rx';
import {Http, Headers, Response} from '#angular/http';
import {User} from './user';
#Injectable()
export class UserService {
constructor(private http: Http) {
}
private oauthUrl = "http://server.techalin.com/oauth/token";
private usersUrl = "http://server.techalin.com/api/users";
getAccessToken() {
var headers = new Headers({
"Content-Type": "application/json",
"Accept": "application/json"
});
let postData = {
grant_type: "password",
client_id: 2,
client_secret: "RGNmOzt7WQ8SdNiCcJKKDoYrsFqI2tudopFjOJU3",
username: "albanafmeti#gmail.com",
password: "password",
scope: ""
}
return this.http.post(this.oauthUrl, JSON.stringify(postData), {
headers: headers
})
.map((res: Response) => res.json())
.catch((error: any) => Observable.throw(error.json().error || 'Server error'));
}
getUsers(accessToken: string): Observable<User[]> {
var headers = new Headers({
"Accept": "application/json",
"Authorization": "Bearer " + accessToken,
});
return this.http.get(this.usersUrl, {
headers: headers
})
.map((res: Response) => res.json())
.catch((error: any) => Observable.throw(error.json().error || 'Server error'));
}
}
and use this service to other component like this
import 'UserService' from './user.service';
export class ExampleCompoent{
constructor(private userService: UserService) {
this.userService.getAccessToken()
.subscribe(data => {
this.getUsers(data.access_token)
});
}
getUsers(accessToken: string) {
this.userService.getUsers(accessToken)
.subscribe(
users => {
this.users = users;
console.log(users);
});
}
}
read more on this link

Resources