0

I was having some problem when trying to call RESTful API from Angular to Spring. Here is my typescript class in Angular:

import { Injectable } from "@angular/core";
import { CATEGORIES } from "./mock-category";
import { Observable, of } from "rxjs";
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Category } from "./category";

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

@Injectable({
  providedIn: "root"
})
export class CategoryService {
  constructor(private http: HttpClient) { }

  private categoryUrl = '/api/category';

  getCategories() {
    return this.http.get<Category[]>(this.categoryUrl);
  }
}

And my controller class in Java:

package controller;

import domain.Category;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import service.CategoryService;
import java.util.List;

@CrossOrigin(origins = "http://localhost:4200", methods = { RequestMethod.POST, RequestMethod.GET, RequestMethod.DELETE,
        RequestMethod.PUT })
@RestController
@RequestMapping({"/api"})
public class CategoryController {

    @Autowired
    private CategoryService categoryService;

    @GetMapping("/categories")
    public List findAll(){
        return categoryService.findAll();
    }
}

I managed to start the maven already but when I try to fetch from Angular, I am getting this error message in console:

zone.js:3243 GET http://localhost:4200/api/category 404 (Not Found)

Any ideas? Thanks in advance!

4 Answers 4

2

That's because you are requesting on url http://localhost:4200/. But on 4200 port your angular app is running, not the backend. Backend will most probably be running on 8080 port, so you need to specify full URL of backend service. like:

private categoryUrl = 'http://localhost:8080/api/categories';

NOTE: I just assumed your backend is running on 8080, you need to add the port on which you are running your backend. Also change /category to /categories as you have specified in your Service

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

9 Comments

Yeap my backend is running on 8080. However, after I changed to the line above, I am getting this error message: Access to XMLHttpRequest at 'localhost:8080/api/category' from origin 'localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
yes thats because in your controller you have resource on /categories but you have mentioned here /category so change it as well
I see I see. I changed it but the CORS error message still persist. Any idea on how can I configure it in Angular?
actually you need to allow cross-platform only in backend, which you did but let me see more to it.
I did added the @CrossOrigin but it does not work still :(
|
0

For your CORS issue you can try this :

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // localhost:4200 (for dev) or YOUR_SERVER:8080 (for production)
        registry.addMapping("/api/**").allowedOrigins("http://localhost:4200", "http://YOUR_SERVER:8080").allowCredentials(true);
    }
}

And here are my headers for client side :

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

Comments

0

Try adding this as java Configuration file under SpringBootApp package:

@Configuration
@EnableWebSecurity
public class AppSecurity extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
         http.csrf().disable().cors().disable().httpBasic()
                .and()
                .authorizeRequests()
                .antMatchers("/api/categories").permitAll()//Permits this api for all
                .anyRequest().authenticated();

    }
}

Comments

0

Drawback of Ans- https://stackoverflow.com/a/56555192/6582610 is you have to change in every ts service file and add domain in every URL rather than you can create Interceptor for this

Use the new HttpClient Interceptor to manipulate your request.

Create a proper injectable that implements HttpInterceptor:

import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http';
import {Observable} from 'rxjs/Observable';

@Injectable()
export class APIInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const apiReq = req.clone({ url: `http://localhost:8080/${req.url}` });
    return next.handle(apiReq);
  }
}

The HttpInterceptor can clone the request and change it as you wish, in this case I added localhost path in your every api URL http://localhost:8080/.

Provide the AppModule with the following configurations:

      provide: HTTP_INTERCEPTORS,
      useClass: APIInterceptor,
      multi: true,
    }
  ]

Now all your requests will start with http://localhost:8080, you don't have to go to every file and change it.Also if you have multiple domain you can configure here with if- else condition.

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.