Internal Server Error When Adding WebMvcConfigurer To Spring Boot Rest Application - java

I have a Spring Boot app and I wanted to allow other origins to make requests because I got the 'cors' error. So I searched and I found this answer: Annotation CrossOrigin not working in Spring boot witch helped for the endpoints that have no body. On the other hand, those who have a body I get Internal Server Error.
Below is the configuration:
#Configuration
#EnableWebMvc
public class CorsConfiguration implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:63343", "http://localhost:3000", "https://smart-booking-ba548.web.app")
.allowedMethods("GET", "POST", "DELETE", "PUT");
}
}
The controllers have the #RestController annotation and the methods #Get/Post|Mapping. They return a ResponseEntity<Object>.

I solved it by putting the following method in main class.
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*");
}
};
}

Related

Is there any way to inject Interceptor from external library in Spring?

I'm developing a jar library and trying to inject an interceptor from external jar library to Application.
For example:
External Lib
MyExternalInterceptor.java
public class MyExternalInterceptor implements HandlerInterceptor {
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// Do something
}
}
I tried to using AOP in external libs but it's not working.
InterceptorAspect.java
#Around("execution(* org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.addInterceptors(..))")
public Object aspect(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
// Tried to inject MyExternalInterceptor here
Object result = proceedingJoinPoint.proceed();
return result;
}
In Application using that lib:
Application
MyConfiguration.java
#Configuration
public MyConfiguration extends WebMvcConfigurationSupport {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SpringTestInterceptor()); // client's own interceptor
/* Add MyExternalInterceptor not explicitly but implicitly using AOP or other things */
}
}
Is there any way to inject an interceptor from external lib to App?
I know the question is very obscure (sorry for that), but could you give me any advice or hint to make it work?
Thank you for anyone who read my question :)
(I updated few more details for clarification)
Summary
Use WebMvcConfigurer in both Client and library side instead of WebMvcConfigurationSupport
AoP is not needed
I use WebMvcConfigurer instead of WebMvcConfigurationSupport and change some codes like below:
External Lib
MyExternalInterceptor.java
Same as before
InterfaceAspect.java
Don't needed it anymore
MyExternalLibConfiguration.java
#Configuration
public class MyExternalLibConfiguration implements WebMvcConfigurer {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyExternalInterceptor());
}
}
Application (client)
MyConfiguration.java
#Configuration
public MyConfiguration implements WebMvcConfigurer {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SpringTestInterceptor()); // client's own interceptor
/* No need to add MyExternalInterceptor in here */
}
}
That's all! Everything is working well as M. Deinum said in comment.
Thank you again Deinum!

Can I use two interceptors on same spring boot application?

I have a Spring Boot application that contains two different dashboards, and so each user can access only one. Actually I have one interceptor that secure one dashboard, but the second dashboard needs another interceptor. This is possible?
This is my configuration class:
#Configuration
public class SecurityConfiguration implements WebMvcConfigurer{
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AutorizadorInterceptorEscola());
}
}
I need to add another interceptor to secure the second dashboard.
Create Configuration Class extends with WebMvcConfigurerAdapter
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new GuestInterceptor());
registry.addInterceptor(new AdminInterceptor());
}

How do you setup not found page in Spring Boot 2 and Angular

In Spring Boot <2 I would do:
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/404").setViewName("redirect:/not-found");
}
#Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
return container -> container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404"));
}
}
But EmbeddedServletContainerCustomizer is now missing, I have tried:
#Bean
public ConfigurableServletWebServerFactory webServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404"));
return factory;
}
but with no luck.
Nevermind, that WAS the actual answer, I forgot to add the error page as a route.
#Controller
public class RouterController {
#RequestMapping({
"/error"
})
public String index() {
return "forward:/index.html";
}
}
Hopefully this will help, that's the way to add a custom error page in Spring Boot 2 with Angular.

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;
}

Swagger2 + Spring REST API not working

I have a Spring Rest controller and its NOT spring boot application. Its just a REST API Project. I want to integrate swagger2 in my project. I tried all the examples in Net and in demo but with no luck. When i try to execute http://localhost:8085/context/swagger-ui.html i get 404 error. Please find my confugration below and let me know if there is any discrepencies. Any help is highly appreciated.
jars - under /WEB-INF/lib
google-collections-1.0.jar
springfox-core-2.2.2.jar
springfox-schema-2.2.2.jar
springfox-spi-2.2.2.jar
springfox-spring-web-2.2.2.jar
springfox-staticdocs-2.2.2.jar
springfox-swagger-common-2.2.2.jar
springfox-swagger-ui-2.2.2.jar
springfox-swagger2-2.2.2.jar
My swagger config class -
#EnableSwagger2
public class SwaggerConfiguration {
}
My springconfig class
#EnableWebMvc
#ComponentScan(basePackageClasses = controller.class)
#Import(SwaggerConfiguration.class)
public class SpringConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
My Application initializer class below as per springfox-java demo . I tried with and without the below class and its not working either way.
Application Initializer class
public class ApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{controller.class};
}
#Override
protected String[] getServletMappings() {
return new String[]{"/*"};
}
}
I can access my rest urls but not swagger-ui.html in the same context.
Please let me know what i am missing here?
I add the manual selection of controllers:
#Configuration
#EnableSwagger2
public class SwaggerConfig {
#Bean
public Docket productApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("my.package.to.api"))
.paths(regex("/product.*")) //optional
.build();
}
}
given details are not sufficient to reproduce/analyse the issue.
But, today I faced similar problem, ofcourse used SpringBoot, and solved myself as below:
as my sample have one controller class and an application class having main method, I created packages as below, and it got solved:
hello
controllers
HelloController
swagger
SwaggerConfig2
HelloApplication

Categories

Resources