the annotation #CrossOrigin("*") not work - java

I had the error "Access to XMLHttpRequest at 'http://localhost:8081/products/getPro' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource" while I have added the annotation #CrossOrigin("*") in my spring boot application
#RestController
#RequestMapping("/products")
#CrossOrigin("*")
public class ProductController {
#Autowired
private ProductService productService;
#PostMapping(value = "/getPro", consumes = {"application/json"}, produces =
{"application/json"})
public ResponseEntity<?> getPro(#RequestBody Product product){
return this.productService.getPro(product);
}
In my Frontend I have :
export class ProductService {
public productModel : Product
private baseUrl = 'http://localhost:8081';
constructor(private http:HttpClient) { }
getPro () {
return this.http.post<Product>(this.baseUrl + "/products/getPro",
JSON.stringify(this.productModel));
}
}
Can anyone help me ?
PS :I am using this application like a feign client I mean in reality I am calling another application with FeignClient ! It can be the problem ?

I will suggest you to get rid of #crossOrigin.
You can do following in your config file
#Configuration
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
 
    #Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");// Your allowed paths here
    }
}
I will recommend you to move that all to angular only by using reverse proxy.
{
"/api": {
"target": "http://localhost:8081",
"secure": false
}
}
See github project here. https://github.com/vohra01/parking-demo-SG/blob/master/IdeaProjects/parking-demo/parking-ui-app/proxy.conf.json

Related

#Path works, but #RequestMapping doesn't Java Spring Boot

This works, I am able to make a request in postman for this Service.
#RestController
#Path("sample")
public class SampleClass {
#GET
#Path(value = "/s1")
public Object get() {
//Something
}
}
The problem is when I try to use #RequestMapping instead of #Path, I get a
404 Not Found
Error.
#RestController
#RequestMapping("sample")
public class CommonService {
#GetMapping(value = "/s1", produces = MediaType.APPLICATION_JSON)
public Object get() {
//Something
}
}
What I am doing wrong here?
After a while, I found out that for the JAX-RS (#Path) I had configured in web.xml file a different route "something".
JAX-RS: localhost:8080**/something**/sample/s1
Spring Rest Services: localhost:8080/sample/s1
I was also missing a "/" in the Spring Rest Service.
#RequestMapping("**/**sample")
Full code bellow:
#RestController
#RequestMapping("/sample")
public class CommonService {
#GetMapping(value = "/s1", produces = MediaType.APPLICATION_JSON)
public Object get() {
//Something
}
}

#GetMapping and RSocketServer with spring-boot-starter-rsocket

Was trying out RSocket Request/Response as specified in section 4 of https://www.baeldung.com/spring-boot-rsocket. So there is a RSocketServer autoconfigured and listening at port 7000. Unable to connect to the method annotated with #GetMapping when hitting the same from browser
#RestController
public class MarketDataRestController {
private final RSocketRequester rSocketRequester;
public MarketDataRestController(RSocketRequester rSocketRequester) {
this.rSocketRequester = rSocketRequester;
}
#GetMapping(value = "/current/{stock}")
public Publisher<MarketData> current(#PathVariable("stock") String stock) {
return rSocketRequester
.route("currentMarketData")
.data(new MarketDataRequest(stock))
.retrieveMono(MarketData.class);
}
}
Expecting to be able to connect to the current() of the class MarketDataRestController annotated with #GetMapping when requesting the same from browser, say e.g.: http://localhost:7000/current/APPLE.
Not sure how to connect to the same.
You can't use #RequestMapping with sockets, use #MessageMapping instead:
instead of #RequestMapping or #GetMapping annotations like in Spring MVC, we will use the #MessageMapping annotation:
#Controller
public class MarketDataRSocketController {
private final MarketDataRepository marketDataRepository;
public MarketDataRSocketController(MarketDataRepository marketDataRepository) {
this.marketDataRepository = marketDataRepository;
}
#MessageMapping("currentMarketData")
public Mono<MarketData> currentMarketData(MarketDataRequest marketDataRequest) {
return marketDataRepository.getOne(marketDataRequest.getStock());
}

Getting 406 Could not find acceptable representation /Spring JSON Test. How to ignore .htm extension in tests?

Controller needs uses .htm extensions for all handlers, including JSON REST endpoints. How should I test for REST endpoints?
Problem:
I cannot disable suffix interpretation and I am getting 406 "Could not find acceptable representation"
Tried attempts:
I reviewed posts on stackoverflow related to 406, but could not find relevant one to the case where 'htm' suffix is used in tests. When you remove '.htm' suffix from both Controller and Test - the test is passing.
Here is controller with /changePassword.htm endpoint:
#Controller
public class MainController {
public static class ResultBean {
private final String result;
public String getResult() {
return result;
}
public ResultBean(String result) {
this.result = result;
}
}
#RequestMapping(value="/changePassword.htm", method= RequestMethod.POST, produces = { "application/json" })
public #ResponseBody ResultBean changePassword (
#RequestParam("username") String username, #RequestParam("password") String password) {
return new ResultBean("OK");
}
}
And here is the test with configuration:
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration(classes = { HomeControllerTest.Config.class })
public class HomeControllerTest {
#InjectMocks
private MainController controller = new MainController();
private MockMvc mvc;
#Configuration
#EnableWebMvc
public static class Config extends WebMvcConfigurerAdapter {
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false)
.favorParameter(true)
.parameterName("mediaType")
.ignoreUnknownPathExtensions(true)
.ignoreAcceptHeader(false)
.useJaf(false)
.defaultContentType(MediaType.APPLICATION_JSON);
}
#Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(false);
}
}
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
mvc = MockMvcBuilders.standaloneSetup(controller)
.build();
}
#Test
public void shouldPassChangePasswordBean() throws Exception {
mvc.perform(post("/changePassword.htm")
.accept("*/*")
.param("username", "example")
.param("password", "abcdef")
)
.andExpect(status().isOk()); // Test produces 406 instead of 200
}
}
Any idea?
On newer version of Spring (4+ I think), mime type is determined from suffix first.
So If you use a .htm suffix, Spring will default to produce HTML even if you don't want to.
One way to bypass this is to use a filter that rewrite URL. For instance tuckey URL rewriter filter
With this, you can set some rules like:
/my/page/that/return/json.htm is rewriten to /my/page/that/return/json so that Spring can produce data according to the Accept header.
with Spring 5, try changing your URL of your web service to .json! that is the right fix. great details here http://stick2code.blogspot.com/2014/03/solved-orgspringframeworkwebhttpmediaty.html

Whitelabel Error Page Spring boot

I recently migrated to Spring boot. I used Spring MVC before. When I go to a site after the application starts, this throws 404 page not found. The controller handles the request, but for some reason does not find the jsp page.
My Application.java:
package com.myapp.webapp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication(scanBasePackages = "com.myapp")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
application.properties
# Spring MVC configuration
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
spring.datasource.url=jdbc:mysql://us-cdbr-iron-east-05.cleardb.net/heroku_4663e71bc0d567a?reconnect=true
spring.datasource.username=bb1a6d3ce29ada
spring.datasource.password=******
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#spring.datasource.url=jdbc:mysql://localhost:3306/socialnet?autoReconnect=true&useSSL=false
#spring.datasource.username=root
#spring.datasource.password=123
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
debug=true
And controller for example
package com.myapp.webapp;
//imports
#Controller
#SessionAttributes({"accountInSession", "base64Photo"})
public class MainController {
private static final Logger logger = LoggerFactory.getLogger(MainController.class);
#Autowired
private AccountService accountService;
#Autowired
private AuthenticationTrustResolver authenticationTrustResolver;
#RequestMapping(value = {"/login", "/"})
public ModelAndView loginPage(#RequestParam(value = "error", required = false) String error,
#RequestParam(value = "logout", required = false) String logout,
#RequestParam(value = "noLogin", required = false) String noLogin) {
ModelAndView modelAndView = new ModelAndView("/login");
if (error != null) {
modelAndView.addObject("error", "Incorrect mail and/or password");
//modelAndView.setViewName("login");
}
if (logout != null) {
modelAndView.addObject("msg", "You've been logged out successfully!");
//modelAndView.setViewName("login");
}
if (noLogin != null) {
modelAndView.addObject("error", "Please log in to view this page");
}
if (!isCurrentAuthenticationAnonymous()) {
//modelAndView.setViewName("login");
modelAndView.setViewName("redirect:/account");
return modelAndView;
}
return modelAndView;
}
#RequestMapping("/test")
public String test() {
return "redirect:/registration";
}
}
For example if I go to http://localhost:8080/test controller redirected me to http://localhost:8080/registration
I used a multi module maven project with models: common(for models), dao, service and webapp.
So controllers located in
java/com/myapp/webapp/controllers
Jsp pages located in
src/main/webapp/WEB-INF/jsp
And path to files:
java/com/myapp/Application.java
src/main/resources/application.properties
And structure of wepapp module
You need to provide your implementation of view resolver using WebMvcConfigurer.
WebMvcConfigurer has replaced the old, deprecated WebMvcConfigurerAdapter.
#EnableWebMvc
#Configuration
#ComponentScan
public class CustomWebConfig implements WebMvcConfigurer {
#Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/jsp/", ".jsp");
}
}
You need to provide prefix(/WEB-INF/jsp/) and suffix(.jsp) explicitly as registry.jsp()method takes default prefix as /WEB-INF/ and suffix as .jsp.
Refer Spring Framework: ViewResolverRegistry class
I have solve this problem. I move all jsp files from src/main/wepapp/WEB-INF/jsp/
to src/main/resources/META-INF/resources/WEB-INF/jsp/. I have no idea why it not works before, but now it works

Delete Method Cors issue in Rest Controller

I have some Rest endpoints in my project which I call from a client application in another server. I have successfully disabled Cors using the #CrossOrigin annotation, and all the methods work fine except the Delete method which throws the following error on Chrome:
XMLHttpRequest cannot load http://localhost:8856/robotpart/1291542214/compatibilities. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8888' is therefore not allowed access. The response had HTTP status code 403.
Here is my controller:
#CrossOrigin(origins = "*")
#ExposesResourceFor(RobotPart.class)
public class RobotPartController {
//All endpoints are working except the Delete Mapping
#GetMapping("/robotpart")
public ResponseEntity<List<RobotPartResource>> listAllParts() {
//..
}
#GetMapping("/robotpart/{id}")
public ResponseEntity<RobotPartResource> getById(#PathVariable Integer id) {
//..
}
#GetMapping("/robotpart/{id}/compatibilities")
public ResponseEntity<Collection<RobotPartResource>> getRobotCompatibilities(#PathVariable Integer id,
//..
}
#PostMapping("/robotpart")
public ResponseEntity<RobotPartResource> getById(#RequestBody #Valid RobotPart newRobot) {
//..
#PutMapping("/robotpart/{id}")
public ResponseEntity<RobotPartResource> modify(#PathVariable Integer id, #Valid #RequestBody RobotPart newRobot) {
//...
}
#DeleteMapping("/robotpart/{id}")
public ResponseEntity<RobotPart> deleteById(#PathVariable Integer id) {
//...
}
}
Any way around it?
I found a solution, after analyzing http requests, I noticed that Access-Control-Allow-Methods header was missing the DELETE method, so I have added it by delete the #CrossOrigin annotation, and adding this bean to the configuration:
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/robotpart/**").allowedOrigins("*").allowedMethods("GET", "POST","PUT", "DELETE");
}
};
}
Adding to the answers above, the reason why disabling CORS won't work for DELETE (but works for GET and POST) is that this is the default behavior for the WebMvcConfigurer as stated here (highlighted in yellow):
Some of the previous answers have been very helpful, however, in my case (spring boot 2.7.4) I had to configure cors like this:
#Configuration
#EnableWebMvc
public class CorsConfiguration implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("GET", "POST","PUT", "DELETE");
}
}
This is my CORS configuration, it may be helpful to somebody
#Bean
CorsConfigurationSource corsConfigurationSource() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration().applyPermitDefaultValues();
corsConfiguration.addAllowedMethod(HttpMethod.DELETE);
corsConfiguration.addAllowedMethod(HttpMethod.PATCH);
source.registerCorsConfiguration("/**", corsConfiguration);
return source;
}

Categories

Resources