SpringBoot and #CrossOrigin annotation with POST only - java

I have the following class
#RestController
#RequestMapping("/bets")
#CrossOrigin
public class BetRestController {
#Autowired
private BetController betController;
#ResponseBody
#RequestMapping(method=RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public BetResource betOnGame(#RequestBody #Valid BetResource betResource) {
return BetTranslator.from(betController.betOnGame(BetTranslator.from(betResource)));
}
#ResponseBody
#RequestMapping(method = RequestMethod.GET)
public List<BetResource> getAllBets() {
return betController.getAllBets().stream().map(BetTranslator::from).collect(Collectors.toList());
}
}
The problem is that when I try to access the POST method I am getting:
XMLHttpRequest cannot load http://localhost:8080/bets. Origin http://localhost:3000 is not allowed by Access-Control-Allow-Origin.
but GET method works.
What I have wrong in my configuration or maybe there is a bug in #CrossOrigin annotation processing?!

If I understand your problem correctly, it is possible to specify CORS origin on one specific method.
Sprint Boot documentation : https://spring.io/guides/gs/rest-service-cors/
Enabling CORS
Controller method CORS configuration
So that the RESTful web service will include CORS access control
headers in its response, you just have to add a #CrossOrigin
annotation to the handler method:
Here's the example from Spring boot website :
#CrossOrigin(origins = "http://localhost:9000")
#RequestMapping("/greeting")
public #ResponseBody Greeting greeting(#RequestParam(required=false, defaultValue="World") String name) {
System.out.println("==== in greeting ====");
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}

Related

How to return json/xml from Spring Boot #Controller?

I'm trying to return JSON/XML from a function of my Controller. First I was using #RestController and it worked good, but now I need to change to #Controller, because I will use also some other functions and pass there some objects for my view.
#Controller
#RequestMapping("/game")
public class ViewController {
#RequestMapping(value = "/statistic", method = RequestMethod.GET,
produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public GamerData[] getStatistic() {
RestTemplate restTemplate = new RestTemplate();
try {
String uri_get_statistic = "http://localhost:8081/statistic/";
ResponseEntity<GamerData[]> response = restTemplate.getForEntity(uri_get_statistic, GamerData[].class);
GamerData[] statisticData = response.getBody();
return statisticData;
} catch(Exception e) {
e.printStackTrace();
return null;
}
}
}
After I've changed to Controller I get error 404 not found. With RestController I've got json. (GamerData is just a class with 2 simple fields (int and String), setters, getters, consructor).
UPDATE:
I've added #ResponseBody to my function, but now I have Internal Server error
Resolved [org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class [Lgame.mainservice.mvc.GamerData;] with preset Content-Type 'null']
try to add #ResponseBody like
public #ResponseBody GamerData[] getStatistic....
#RequestMapping(value = "/statistic", method = RequestMethod.GET,
produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
#ResponseBody // add this one
public GamerData[] getStatistic() {}
Thank you all for answers, I've added #ResponceBody annotation to my function and removed "produces" part from #RequestMapping annotation and my function works great:
#RequestMapping(value = "/statistic", method = RequestMethod.GET)
#ResponseBody
public GamerData[] getStatistic() {
//function code
}

Log url to Spring controller from inside it

Suppose you have a Spring MVC controller, something like this
#Controller
public class RestController {
#GetMapping(value = "/test")
public #ResponseBody Test getTestData(...) {
// console log path to controller: http://localhost:80/app/test
return testData;
}
}
Is it possible to log/print from inside the controller the url to it? In the example above the output would be something like https://localhost:80/app/test
Using .getRequestUrl from the servlet is not behaving correctly.
You can inject UriComponentsBuilder as parameter then use the method toUriString(). From the documentation, it is used to build a relative URI from the current request’s, this should work as your are expected Doc.
#Controller
public class RestController {
...
#GetMapping(value = "/test")
public #ResponseBody Test getTestData(UriComponentsBuilder ucb, ...) {
LOGGER.debug(ucb.toUriString());
// console log path to controller: http://localhost:80/app/test
return testData;
}
...
}

#CrossOrigin not working Spring Boot. How can I fix It?

I'm using Spring Boot to make a REST Api for my Vue application. This is my route handler:
#RestController
public class RootController {
#CrossOrigin
#GetMapping("/")
public String index() {
return "Hello from server";
}
}
Whenever I use axios to make a request to my API it responds with:
How can I fix this?
Basically, you need to specify the origin with the #CrossOrigin annotation, that lets the spring app know which all origins are allowed to make request to those rest api's.
In your case, you can try replacing #CrossOrigin with #CrossOrigin(origins = "http://localhost:8080") assuming your client application is hosted at port 8080.
Also, you can try #CrossOrigin(origins = "", allowedHeaders = "") which would allow every origin and all headers.
#CrossOrigin
#RestController
public class RootController {
#GetMapping("/")
public String index() {
return "Hello from server";
}
}
I would highly recommend that you go to this Spring.io article that covers in-depth what you are asking for!
For the meantime, you can go and create a #Bean that would configure CORS for your application (Consider converting the code into Java syntax, I've just copied it from a kotlin project I'm working on):
#Bean
fun corsFilter(): CorsWebFilter {
val corsConfig = CorsConfiguration()
corsConfig.allowedOrigins = Arrays.asList("*")
corsConfig.maxAge = 8000L
corsConfig.addAllowedMethod("PUT")
corsConfig.addAllowedMethod("GET")
corsConfig.addAllowedMethod("POST")
corsConfig.addAllowedHeader("Origin")
corsConfig.addAllowedHeader("Content-Type")
corsConfig.addAllowedHeader("Accept")
val source = UrlBasedCorsConfigurationSource()
source.registerCorsConfiguration("/**", corsConfig)
return CorsWebFilter(source)
}

Root path works for all HTTP methods

I have a spring boot application.yml where context path is mentioned as below.
server:
servlet:
contextPath: /home
I have the following RootController.java
#RestController
#Slf4j
#RequestMapping("/")
public class RootController {
#RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public String getContent() throws IOException {
return "This is root content";
}
}
But the root endpoint works for all HTTP methods like 'POST', 'PUT', etc., even though method is mentioned as 'GET' in #RequestMapping. It is supposed to work only for GET method. I'm not sure about the problem. Can someone help fix this ?

Spring 5 consume multiple MediaType

I'm using Spring boot 1.5.8.RELEASE
I have an endpoint and would like to consume multiple MediaType.
In particular application/x-www-form-urlencoded and application/json type.
At the moment I have the below code. It works for application/x-www-form-urlencoded, but doesn't work for application/json.
#RequestMapping(path = "/abc", method = RequestMethod.POST,
consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_FORM_URLENCODED_VALUE},
produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseStatus(value = HttpStatus.OK)
public ResponseEntity<MyResponse> validate(#Valid #ModelAttribute MyDetails details) {
return something();
}
I tried to put a content negotiator in my configuration, but still doesn't work.
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false)
.defaultContentType(MediaType.APPLICATION_JSON)
.mediaType("x-www-form-urlencoded", MediaType.APPLICATION_FORM_URLENCODED);
}
How can I allow the endpoint to accept these 2 media types?
exchange {} to [] for consumes
Try it:
consumes = [MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_FORM_URLENCODED_VALUE],
reference: Spring RequestMapping - Baeldung

Categories