1

I get the following exception when making an OPTIONS request:

java.lang.NullPointerException: null
at org.springframework.data.rest.webmvc.RepositoryRestHandlerMapping.exposeEffectiveLookupPathKey(RepositoryRestHandlerMapping.java:264) ~[spring-data-rest-webmvc-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.data.rest.webmvc.RepositoryRestHandlerMapping.lookupHandlerMethod(RepositoryRestHandlerMapping.java:165) ~[spring-data-rest-webmvc-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:368) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:65) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:401) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping$HandlerSelectionResult.from(DelegatingHandlerMapping.java:108) ~[spring-data-rest-webmvc-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping.getHandler(DelegatingHandlerMapping.java:74) ~[spring-data-rest-webmvc-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1231) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1014) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doOptions(FrameworkServlet.java:944) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:669) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.13.jar:9.0.13]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.13.jar:9.0.13]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320) ~[spring-security-web-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) ~[spring-security-web-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) ~[spring-security-web-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) ~[spring-security-web-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) ~[spring-security-web-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) ~[spring-security-web-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.

The request I am making is:

curl 'http://localhost:9091/api/authors' -X OPTIONS -H 'Access-Control-Request-Method: GET' -H 'Origin: http://localhost:3000'

I'm doing this to mimic a pre-flight request from my front end where I originally noticed the problem.

If I remove the 'Access-Control-Request-Method' header from the request, everything proceeds normally.

I am using SpringBoot version 2.1.1. Here are my dependencies:

dependencies {
    implementation('org.springframework.boot:spring-boot-starter-security')
    implementation('org.springframework.boot:spring-boot-starter-data-jpa')
    implementation('org.springframework.boot:spring-boot-starter-web')
    runtimeOnly('com.h2database:h2')
    testImplementation('org.springframework.boot:spring-boot-starter-test')

    compile 'org.springframework.boot:spring-boot-starter-data-rest:2.0.3.RELEASE'
}

and this is my security config:

@Configuration
@EnableWebSecurity(debug=true)
public class SecurityConfig  extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    }
}

You can find a demo project here: https://github.com/cekali/spring-problem

I really appreciate any help that anyone can provide, I am stumped

cekali
  • 23
  • 4

2 Answers2

2

It's a bug in RepositoryRestHandlerMapping's exposeEffectiveLookupPathKey method. Although it has been fixed on Github, the latest version (3.1.4.RELEASE) has not been unfortunately.

Further information: The exception is thrown because the method expects a RequestMappingInfo object that encapsulates information from the @RequestMapping annotation on the HandlerMethod. But for preflight requests, the HandlerMethod that is returned and subsequently used (see AbstractHandlerMethodMapping) has no such annotation, so the RequestMappingInfo object is null. Calling methods on it will of course throw a NullPointerException.

This is the fix you'll see on Github:

private void exposeEffectiveLookupPathKey(HandlerMethod method, HttpServletRequest request, String repositoryBasePath) {

    RequestMappingInfo mappingInfo = getMappingForMethod(method.getMethod(), method.getBeanType());

    if (mappingInfo == null) {
        return;
    }

    ...
}

UPDATE This was fixed in 3.1.5.RELEASE

NatFar
  • 2,090
  • 1
  • 12
  • 29
  • any thoughts on how I can fix this within my application? My solution at the moment is to downgrade spring-boot to 2.0.5.RELEASE – cekali Feb 13 '19 at 16:54
0

You can customize your prefilght requests as follow:

I have user Spring Boot 2.1.3.RELEASE

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.cors().and()       
        .authorizeRequests()
        .antMatchers("/**",).permitAll() //custom logic
        ...................
        .............
    }


    //define the Corsbean and add your cutom headers here
    @Bean
    CorsConfigurationSource corsConfigurationSource() {
         CorsConfiguration configuration = new CorsConfiguration();
         configuration.setAllowedOrigins(Arrays.asList("*"));
         configuration.setAllowCredentials(true);
         configuration.setAllowedHeaders(Arrays.asList("Access-Control-Allow-Headers","Access-Control-Allow-Origin",
                 "Access-Control-Request-Method", "Access-Control-Request-Headers","Origin","Cache-Control",
                 "Content-Type", "Authorization"));
         configuration.setAllowedOrigins(Arrays.asList("*"));
         configuration.setAllowedMethods(Arrays.asList("*"));
         UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
         source.registerCorsConfiguration("/**", configuration);
         return source;
     }

}
DEBENDRA DHINDA
  • 1,163
  • 5
  • 14