2

I setup a fairly simple secure application using spring boot, but I keep getting this exception from the server after I successfully log in:

javax.servlet.ServletException: Filter execution threw an exception
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:116)
org.springframework.boot.context.web.ErrorPageFilter.access$000(ErrorPageFilter.java:60)
org.springframework.boot.context.web.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:91)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:109)

root cause

java.lang.AbstractMethodError
    javax.servlet.http.HttpServletRequestWrapper.changeSessionId(HttpServletRequestWrapper.java:290)
    javax.servlet.http.HttpServletRequestWrapper.changeSessionId(HttpServletRequestWrapper.java:290)
    sun.reflect.GeneratedMethodAccessor295.invoke(Unknown Source)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:497)
    org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:203)
    org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:188)
    org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy.applySessionFixation(ChangeSessionIdAuthenticationStrategy.java:48)
    org.springframework.security.web.authentication.session.AbstractSessionFixationProtectionStrategy.onAuthentication(AbstractSessionFixationProtectionStrategy.java:82)
    org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy.onAuthentication(ChangeSessionIdAuthenticationStrategy.java:32)
    org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy.onAuthentication(CompositeSessionAuthenticationStrategy.java:83)
    org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:216)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:105)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:116)
    org.springframework.boot.context.web.ErrorPageFilter.access$000(ErrorPageFilter.java:60)
    org.springframework.boot.context.web.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:91)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:109)

Here is my initializer class:

@EnableAutoConfiguration
@SpringBootApplication
public class RecruitingDashboardApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(RecruitingDashboardApplication.class);
    }

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


}

And my viewResolver configuration class:

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Bean 
    public ViewResolver viewResolver() {
        ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
        templateResolver.setPrefix("templates/");
        templateResolver.setSuffix(".html");

        SpringTemplateEngine engine = new SpringTemplateEngine();
        engine.setTemplateResolver(templateResolver);

        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(engine);
        return viewResolver;
    }


    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("dashboard");
        registry.addViewController("/login").setViewName("login");
    }

}

And finally my security configuration class:

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

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

        http.headers()
                .frameOptions()
                .disable()
            .authorizeRequests()
                .antMatchers("/css/**", "/img/**", "/fonts/**").permitAll()
                .anyRequest()
                .authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("username").password("password").roles("USER");
    }

}

These are the pom dependencies I'm using:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>net.sourceforge.nekohtml</groupId>
        <artifactId>nekohtml</artifactId>
        <version>1.9.22</version>
    </dependency>

</dependencies>

Any help is appreciated. I've spend three days on this problem and I've searched everywhere on the web, but I could not find a solution.

UPDATE

It seems I don't get the exception when deploying to Tomcat 8. I only get it on Tomcat 7.

UPDATE 2

I've updated my pom file to include the spring-boot-starter-tomcat dependency with a providedscope. I've also excluded that same transient dependency from spring-boot-starter-web, as described in this question. However, the problem still persists.

3
  • Looks like wrong dependency version. changeSessionId method is defined in Servlet API 3.1 and you probably have 3.0.1 in you classpath. Commented Aug 21, 2015 at 14:49
  • Sounds right. But how do I change it, if all the spring boot starter dependencies are all bundled up? Commented Aug 21, 2015 at 15:48
  • Also, isn't version 3.1 only available on Tomcat 8? I'm have <tomcat.version>7.0.63</tomcat.version> on my properties and I thought that would take care of getting the right dependencies. Commented Aug 21, 2015 at 16:03

1 Answer 1

0

You are deploying a war-based artifact. spring-boot-starter-web provides an embedded web container (Tomcat by default) and the servlet-api goes with it obviously. The container on which you deploy the war uses another version of the API.

You need to flag spring-boot-starter-tomcat with the provided scope so that your war does not bring that extra dependency along. The Spring Boot maven plugin is able to detect that and places such provided dependencies in a separate location of the fat war so that you can still run it from the command line (java -jar yourapp.war). You are free not to use that and just build a regular war file. Don't use the Spring Boot maven plugin in such scenario.

This is explained in the documentation

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you for your answer. I've made the changes you proposed, (see update to question) but the problem still persists.
What can I say? it's essentially the same problem, servlet-api is provider by another dependency of your project. Run mvn dependency:tree to look who is the culprit. You can also look at WEB-INF/lib quickly and make sure no servlet related jars are in there.
After looking at a comment on this question I deleted servlet-api from my tomcat/lib folder. I believe the answer in this case was a combination of the changes you recommended to the pom.xml file and cleaning the tomcat/lib folder.
not at all! You shouldn't mess with your tomcat/lib since this is the original jar that the server must be using. Like I said, you must have servlet-api (either shaded or with a different name maybe) in your war. That's what is causing the issue.
I have checked my war file and there is no servlet-api in WEB-INF/lib. I also ran mvn dependency:tree, which revealed nothing. If its under a different name, I don't know how else I could possibly figure out where it is.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.