13

I have a simple spring boot service running in a docker container exposed on port 8080 that is calling a mysql database.

When I hit localhost:8080/blogs, I get back [{"author":"Christopher Bolton","title":"Test Title 1","content":"This is some content","date":"2017-08-29"}]

This is working just fine when I hit it directly in the browser. However, when I try it from jQuery I am getting the normal Access-Control-Allow-Origin.

Here is my spring boot service:

@SpringBootApplication
@RestController
public class ChrisboltonServiceApplication {

public static void main(String[] args) {
    SpringApplication.run(ChrisboltonServiceApplication.class, args);
}

@Autowired
private JdbcTemplate jdbcTemplate;

@CrossOrigin
@RequestMapping(path="/blogs")
public @ResponseBody Iterable<ChrisBolton> getAllUsers() {
    List<ChrisBolton> result = jdbcTemplate.query(
            "SELECT * FROM blog",
            (rs, rowNum) -> new ChrisBolton(rs.getString("author"), 
                                               rs.getString("title"), 
                                               rs.getString("content"), 
                                               rs.getDate("date"))
    );

    return result;
}
}

Here is my jQuery:

$.ajax({
  url: "http://localhost:8080/blogs",
  crossDomain: true
}).done(function(data) {

  console.log(data);
});

But I am still getting this error:

XMLHttpRequest cannot load http://localhost:8080/blogs. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.

I have tried this by adding the @CrossOrigin to the getAllUsers() method and I have tried at the class level. I have also looked at this because I am running my UI on port 3000. But that link is not spring specific.

EDIT

Adding my request headers:

GET /blogs HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Accept: */*
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) 
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 
Safari/537.36
Referer: http://localhost:3000/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8

Response in network tab (Chrome):

[{"author":"Christopher Bolton","title":"Test Title 1","content":"This is some content","date":"2017-08-29"}]

So it looks like I am getting data back in the network tab. However, my console.log(data) produces the Access-Control-Allow-Origin

Chris Bolton
  • 2,162
  • 4
  • 36
  • 75

3 Answers3

16

Try adding this to your application:

@SpringBootApplication
@RestController
public class ChrisboltonServiceApplication {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedOrigins("*");
            }
        };
    }

...

Also, try removing the crossDomain: true from the $.ajax().

acdcjunior
  • 132,397
  • 37
  • 331
  • 304
  • do i still keep `@CrossOrigin`? Still getting same error. – Chris Bolton Sep 06 '17 at 00:55
  • also, i added above the fact that i am using docker and exposing port 8080. Maybe this could be part of the issue? – Chris Bolton Sep 06 '17 at 00:57
  • Actually, everything should have been working with `@CrossOrigin` alone. I just tested here and it works fine. The fact that you use a docker container should be affecting it. What image is your container based? Isn't there some kind of proxy in front of the spring boot inside the container? – acdcjunior Sep 06 '17 at 01:00
  • The container is running on my machine and the spring boot app is exposed on port `8080`. My UI is running on port `3000`. So it's `localhost` calling `localhost` on different ports. Is there some proxy concept I am missing here? – Chris Bolton Sep 06 '17 at 13:42
  • No. I meant if the container had a proxy (like nginx) in front of the spring boot app. But it seems unlikely. Do you see the CORS headers in the response at the network tab when you request and get an error? – acdcjunior Sep 06 '17 at 17:25
  • So in the network tab I am actually getting the data back from the server. So now I am even more confused on why I am getting this error in the console. – Chris Bolton Sep 06 '17 at 20:17
  • Not the data, but the CORS headers, are they present? – acdcjunior Sep 06 '17 at 20:24
  • No I do not see the CORS in the response. – Chris Bolton Sep 07 '17 at 02:13
  • Maybe your spring boot application is not reloading, not recompiling and applying the CORS-addition changes. Can you show us how you build your project? The `Dockerfile`, maybe? – acdcjunior Sep 07 '17 at 02:50
  • Okay, i wiped all my images and stopped containers... Then I did my normal `mvn clean install` and `docker build -t chrisbolton-service .` My guess is that it wasn't picking up the changes because i wasn't tagging it? – Chris Bolton Sep 08 '17 at 00:02
  • Unlikely. Did the problem go away? Other changes (create a controller that returns a string) get picked up? If so, this theory does not hold – acdcjunior Sep 08 '17 at 00:31
  • 1
    Yeah, it did work. Getting the response back as expected now. Didn't change anything just wiped all my containers and rebuilt my image from scratch. I was rebuilding my jar and importing it into my container every time. Not 100% what was happening. But docker was the issue. – Chris Bolton Sep 08 '17 at 13:05
5

JUST ADD DevConfiguration in any package then update application.properties file

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@Profile("development")
public class DevConfiguration implements WebMvcConfigurer {
 
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS").allowedOrigins("*");
    }
}

Update application.properties file

# application.properties
spring.profiles.active=development
server.port=8090
abhinavsinghvirsen
  • 1,853
  • 16
  • 25
0

You can add @CrossOrigin("http://localhost:8080") to proper method if you want :8080 to allow request there. It's a simple config for one endpoint/controller. You can use variable there too for customization later of course.

Artur Czopek
  • 292
  • 1
  • 9
  • 1
    I know that you're technically right, but that is bad advice. People see one off configurations and apply them to the N places they are applicable in their code. – Virmundi May 07 '18 at 18:53