Search code examples
javaangularspring-bootspring-data-rest

fields in retrieved mysql database object are all undefined


I'm trying to make a login component with angular 4. In the backend Spring boot, Spring Data Rest and a MySQL database are used. When I want to check the submitted login details with the login credentials of a retrieved account i'm unable to do so because all the fields in the retrieved account object are undefined while the object itself is not undefined (I check this with an if structure). Could someone take a look at my code and tell where the problem is? I'll start with the angular 4 classes and service, then the account pojo and Spring REST repository.

Angular 4 classes:

import {Person} from "./Person";
import {Role} from "./Role";
export class Account {
  id: number;
  username: string;
  password: string;
  person: Person;
  roles: Role[];

}

export class LaborPeriod{
    id: number
    beginDate: Date
    endDate: Date
    hours: number
}

import {LaborPeriod} from "./LaborPeriod";
export class Person{
    id:number
    name:string
    laborPeriods:LaborPeriod[]
}


export class Role{
    id: number
    name: string
}

login component class:

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css'],
  providers: [AccountService]
})
export class LoginComponent {
  title: string;
  loginForm: FormGroup;

  constructor(private fb: FormBuilder,
              private accountService: AccountService,
              private router: Router) {
    this.title = "Inloggen";
    this.loginForm = fb.group({
      email: ['', [Validators.required, Validators.email]],
      password: ['', Validators.required]
    });
  }

  onSubmit() {
    const formModel = this.loginForm.value;

    const account: Account = this.accountService.authenticate(formModel.email, formModel.password);
    console.log(account.id + " " + account.password + " " + " " + account.username)
    console.log(account !== undefined)
    // if (account !== undefined) {
    //   this.router.navigate(["account/update", account.id]);
    // }
    // else{/*username or password doesent exist*/}
  }
}

relevant method in accountservice

  authenticate(username: string, password: string): Account {
    return this.restapi.postCredentials(username, password);
  }

restApi:

@Injectable()
export class RestApiService {
  apiUrl: string = "/api/accounts";
  apiPostUrl: string = "api/accounts/search/findByUsernameAndPassword";
  data: Account;


  constructor(private http: Http) {}

  getData(){
    return this.http.get(this.apiUrl).map((res: Response) => res.json())
  }

  getContacts(){
    this.getData().subscribe(data=> {console.log(data); this.data = data})
  }

  postCredentials(username:string, password:string): Account {
    let params = new URLSearchParams();
    params.append("username", username);
    params.append("password", password);
    // params.set("username", "[email protected]");
    // params.set("password", "12345");
    this.http.get(this.apiPostUrl, {params: params}).map((res: Response) => res.json()).subscribe(data=> { this.data = data});
    console.log(this.data);
    return this.data;
  }

}

now for everything at the backend

@Entity
public class Account {
    @Id
    @GeneratedValue
    private Long id;
    private String username;
    private String password;
    @ManyToMany(cascade = CascadeType.ALL)
    private List<Role> roles;
    @OneToOne(cascade = CascadeType.ALL)
    private Person person;

@Entity
public class LaborPeriod {
    @Id
    @GeneratedValue
    private Long id;
    private Instant beginDate;
    private Instant endDate;
    private Integer hours;

@Entity
public class Role {
    //
    @Id
    @GeneratedValue
    private Long id;
    private String name;

@Entity
public class Person {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    @OneToMany(cascade = CascadeType.ALL)
    private Collection<LaborPeriod> laborPeriods;

account repository

@RepositoryRestResource
public interface AccountRepository extends JpaRepository<Account, Long> {
    Account findByUsername(@Param("username") String username);
    Account findByUsernameAndPassword(@Param("username") String username, @Param("password") String password);
}

Help would be much appreciated.


Solution

  • You need to return an Observable from your post request. This is asynchronous, so your response is available in your callback. Even if you would try and do that from your callback subscribe, this is not possible, since again, this is asynchronous. So what you need to return from your post request is an Observable:

    return this.http.get(this.apiPostUrl, {params: params})
      .map((res: Response) => res.json())
    

    Here you could actually skip the authenticate method from between, I don't see how it's useful for you here. But if you want to keep it, of course you can :)

    So what you would then do, is to subscribe to this post request in your component.

    constructor(private restApiService: RestApiService /** **/) { }
    
    onSubmit() {
      const formModel = this.loginForm.value;
      this.restApiService.postCredentials(formModel.email, formModel.password);
        .subscribe(.....)
    }
    

    worth reading: How do I return the response from an Observable/http/async call in angular2?