0

I'm using Angular 12 CLI and Spring Boot 2.5.5. Using an Angular service, I'm trying to pass a JSON from a component to Spring Boot, using a POST http request. After the JSON arrives in Spring Boot, I need to print it in console, but I can't get it to work. Using Postman, I correctly visualize the JSON, so I think the problem is front-end side. Here's some code:

users.service.ts

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { HttpHeaders } from '@angular/common/http';

import { Observable } from 'rxjs';
import { User } from 'src/user';

@Injectable({
  providedIn: 'root'
})
export class UsersService {

  constructor(private http: HttpClient) { }
  
  getUsers(): Observable<User[]>{
    return this.http.get<User[]>("http://localhost:8080/user/all")
  }

  addNewUser(user: User): void {

    const httpOptions = { 
      headers: new HttpHeaders(
        { 'Content-Type': 'application/json' }
      ) 
    };

    let userJSON = JSON.stringify(user);
    this.http.post("http://localhost:8080/user/add", userJSON, httpOptions);
  }
}

UserController

package com.sporthub.backend.controller;

import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.sporthub.backend.model.Role;
import com.sporthub.backend.model.User;
import com.sporthub.backend.repository.RoleRepository;
import com.sporthub.backend.repository.UserRepository;

@Controller
@CrossOrigin(origins = "http://localhost:4200")
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserRepository userRepo;
    
    @Autowired
    private RoleRepository roleRepo;
    
    @GetMapping("/all")
    public @ResponseBody Iterable<User> getUsers(){
        return userRepo.findAll();
    }
    
    @PostMapping("/add")
    public @ResponseBody String addUser(@RequestBody String user) {

            System.out.println(user);
            return user;
    }
}

HTML Form

<form [formGroup]="checkoutForm" (ngSubmit)="onSubmit()">
  <div>
    <label for="name">
      Name
    </label>
    <input type="text" id="name" formControlName="name">
  </div>

  <div>
    <label for="lastname">
      lastname
    </label>
    <input type="text" id="lastname" formControlName="lastname">
  </div>
  
  <input type="submit" value="Add new user">
</form>

Users Component

import { Component, OnInit } from '@angular/core';
import { User } from 'src/user';
import { UsersService } from '../users.service';
import { FormBuilder } from '@angular/forms';


@Component({
  selector: 'app-users',
  templateUrl: './users.component.html',
  styleUrls: ['./users.component.css']
})
export class UsersComponent implements OnInit {

  users : User[] = [];

  checkoutForm = this.formBuilder.group({
    name: '',
    lastname: ''
  });

  constructor(
    private usersService: UsersService,
    private formBuilder: FormBuilder
  ) { }

  onSubmit(): void {

    let name = this.checkoutForm.get('name')?.value;
    let lastname = this.checkoutForm.get('lastname')?.value;

    let user: User = {
      "name": name,
      "lastname": lastname
    };

    console.log(user);
    this.usersService.addNewUser(user);
  }

  ngOnInit(): void {
    this.getUtenti();
    console.log(this.users);
  }

  getUsers() : void{
     this.usersService.getUsers().subscribe(users => this.users = users);
  }

}
2
  • There is no need to JSON.stringify the body beforehand. Just pass in the object and let Angular's magic do the work :) Commented Oct 27, 2021 at 9:18
  • @jBuchholz thanks for the hint. That didn't solve the problem by the way :( Commented Oct 27, 2021 at 9:34

2 Answers 2

1

You're adding a Content Type header in your client side's webservice, but not telling your backend about it.

I think you should refactor your @PostMapping method to:

 @PostMapping(path = "/add", produces = MediaType.APPLICATION_JSON_VALUE) // <- here
    public @ResponseBody String addUser(@RequestBody String user) {

            System.out.println(user);
            return user;
    }

Alternatively, you can add it to the @RequestMapping, so that it would be applicable for all controller's methods.


BTW: you're returning a String not an object (that would be parsed to a json)

So I suggest that you change your @RequestBody String user to @RequestBody YourUserDtoBackendType user and remove JSON.stringify(user) and pass a user directly in the webservice's client side body, then the serialization/deserialization should be automatically executed via Jackson (which Spring Boot provides a builtin support for it)

Sign up to request clarification or add additional context in comments.

1 Comment

Adding produces = MediaType.APPLICATION_JSON_VALUE didn't solve the problem. I had to change something in my code (adding an Observable as return type and a subscribe for the method calling inside my component). I answered right below, check it.
0

Used an Observable as return type for my addNewUser function inside my UsersService

    addNewUser(user: User): Observable<User> {

    return this.http.post<User>("http://localhost:8080/user/add", user, this.httpOptions);
  }

Then I added a .subscribe() method in my onSubmit() function inside my component.

this.usersService.addNewUser(user).subscribe(user => console.log(user));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.