title: Custom ExceptionTranslationFilter in spring 4 to handle REST AuthenticationException
body: <p>I have a spring MVC RESTful application secured by spring security. Client side is Angular JS.
  But my login and logout pages are plain jsp and I do form based login and log out. upon success full authentication, I load my secured  page(it uses anlgularJS and RESTful api). </p>
  
  <p>I need help in handling AuthenticationException &amp; AccessDeniedException  when REST api is called.
  I extended ResponseEntityExceptionHandler and I am able to catch AccessDEniedException and throw a json response. 
  I understand to handle AuthenticationException ( so I can stop 302 redirection in case of rest full request ) I need to extend ExceptionTranslationFilter. 
  Most of the example I found use XML config. But Is it possible to do in Java config ?</p>
  
  <p>I did write a component to extend ExceptionTranslationFilter  and created a custom AuthenticationEntryPoint, But I am not sure, how to inject it into my ExceptionTranslationFilter  </p>
  
  <p>I get an error 
  Caused by: java.lang.IllegalArgumentException: authenticationEntryPoint must be specified
  I tried adding a constructor, but it thors method not found.
  Any help to solve is appreciated.</p>
  
  <p><strong>MyAuthenticationEntryPoint</strong> </p>
  
  <pre><code>@Service
  public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {
  
      @Override
      public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException arg2)
              throws IOException, ServletException {
          response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
                  "Unauthorized.");
  
      }
  
  }
  </code></pre>
  
  <p><strong>My ExceptionTranslationFilter</strong> </p>
  
  <pre><code>@Component
  public class RestExceptionTranslationFilter extends ExceptionTranslationFilter {
      public static final Logger LOGGER = LoggerFactory.getLogger(RestExceptionTranslationFilter.class);
  
      @Override
      protected void sendStartAuthentication(HttpServletRequest req, HttpServletResponse resp, FilterChain chain, AuthenticationException reason)
              throws ServletException, IOException {
  
              boolean isAjax = "XMLHttpRequest".equals(req.getHeader("X-Requested-With"));
  
          if (isAjax) {
  
              String jsonObject = "{\"message\":\"Please login first.\"," + "\"access-denied\":true,\"cause\":\"AUTHENTICATION_FAILURE\"}";
                  String contentType = "application/json";
                  resp.setContentType(contentType);
                  PrintWriter out = resp.getWriter();
                  out.print(jsonObject);
                  out.flush();
                  out.close();
                  return;
              }
  
          super.sendStartAuthentication(req, resp, chain, reason);
      }
  
  }
  </code></pre>
  
  <p><strong>Security Config</strong></p>
  
  <pre><code>@Configuration
  @EnableWebSecurity
  @EnableWebMvcSecurity
  @EnableGlobalMethodSecurity(securedEnabled = true)
  public class SecurityConfig extends WebSecurityConfigurerAdapter {
  
      public static final Logger LOGGER = LoggerFactory.getLogger(SecurityConfig.class);
  
      @Autowired
      UserDetailsRepository userDetailsRepository;
  
      /**
       * In Memory Authentication
       * @param auth
       * @throws Exception
       */
      @Autowired
      public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
          auth.userDetailsService(userDetailsRepository);
      }
  
  
      @Override
      public void configure(WebSecurity web) throws Exception {
          web.ignoring().antMatchers("/resources/**");
  
      }
  
      @Override
      public void configure(HttpSecurity http) throws Exception {
          LOGGER.debug("Configuring Spring Security HttpSecurity...");
          http.authorizeRequests().antMatchers("/api/**").authenticated();
          http.authorizeRequests().antMatchers("/app.html").authenticated();
          http.authorizeRequests().antMatchers("/login**").permitAll();
          http.authorizeRequests().and().formLogin().loginProcessingUrl("/login").loginPage("/login.jsp").defaultSuccessUrl("/app.html").and()
              .authorizeRequests().and().logout().logoutUrl("/logout").logoutSuccessUrl("/logout.html").permitAll();
          http.csrf().disable();
      }
  
      @Bean
      public static ExceptionTranslationFilter exceptionTranslationFilter() {
          RestExceptionTranslationFilter exceptionTranslationFilter = new RestExceptionTranslationFilter(new RestAuthenticationEntryPoint());
          RestAccessDeniedHandler accessDeniedHandlerImpl = new RestAccessDeniedHandler();
          exceptionTranslationFilter.setAccessDeniedHandler(accessDeniedHandlerImpl);
          exceptionTranslationFilter.afterPropertiesSet();
          return exceptionTranslationFilter;
      }
  }
  </code></pre>
  
  <p><strong>Error Log</strong></p>
  
  <pre><code>2015-01-14_23:10:17.270 DEBUG o.s.security.web.FilterChainProxy - doFilter -
                  /org/hmie/fms/sy/myAccount.html at position 6 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
  2015-01-14_23:10:17.270 DEBUG o.s.security.web.FilterChainProxy - doFilter -
                  /org/hmie/fms/sy/myAccount.html at position 7 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
  2015-01-14_23:10:17.270 DEBUG o.s.security.web.FilterChainProxy - doFilter -
                  /org/hmie/fms/sy/myAccount.html at position 8 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
  2015-01-14_23:10:17.270 DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - doFilter -
                  Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
  2015-01-14_23:10:17.270 DEBUG o.s.security.web.FilterChainProxy - doFilter -
                  /org/hmie/fms/sy/myAccount.html at position 9 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
  2015-01-14_23:10:17.270 DEBUG o.s.s.w.s.SessionManagementFilter - doFilter -
                  Requested session ID CC2CA43BAE60F06F2431C9280A74081F is invalid.
  2015-01-14_23:10:17.270 DEBUG o.s.security.web.FilterChainProxy - doFilter -
                  /org/hmie/fms/sy/myAccount.html at position 10 of 12 in additional filter chain; firing Filter: 'RestExceptionTranslationFilter'
  2015-01-14_23:10:17.270 DEBUG o.s.security.web.FilterChainProxy - doFilter -
                  /org/hmie/fms/sy/myAccount.html at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
  2015-01-14_23:10:17.270 DEBUG o.s.security.web.FilterChainProxy - doFilter -
                  /org/hmie/fms/sy/myAccount.html at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
  2015-01-14_23:10:17.270 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - matches -
                  Checking match of request : '/org/hmie/fms/sy/myaccount.html'; against '/login.jsp'
  2015-01-14_23:10:17.270 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - matches -
                  Checking match of request : '/org/hmie/fms/sy/myaccount.html'; against '/login'
  2015-01-14_23:10:17.286 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - matches -
                  Checking match of request : '/org/hmie/fms/sy/myaccount.html'; against '/logout.html'
  2015-01-14_23:10:17.286 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - matches -
                  Checking match of request : '/org/hmie/fms/sy/myaccount.html'; against '/ess/partials/alertpopup.html'
  2015-01-14_23:10:17.286 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - matches -
                  Checking match of request : '/org/hmie/fms/sy/myaccount.html'; against '/partials/alertpopup.html'
  2015-01-14_23:10:17.287 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - matches -
                  Checking match of request : '/org/hmie/fms/sy/myaccount.html'; against '/fms/**'
  2015-01-14_23:10:17.287 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - beforeInvocation -
                  Secure object: FilterInvocation: URL: /org/hmie/fms/sy/myAccount.html; Attributes: [authenticated]
  2015-01-14_23:10:17.287 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - authenticateIfRequired -
                  Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
  2015-01-14_23:10:17.287 DEBUG o.s.s.access.vote.AffirmativeBased - decide -
                  Voter: org.springframework.security.web.access.expression.WebExpressionVoter@5fcd184d, returned: -1
  2015-01-14_23:10:17.298 DEBUG o.s.s.w.a.ExceptionTranslationFilter - handleSpringSecurityException -
                  Access is denied (user is anonymous); redirecting to authentication entry point
  org.springframework.security.access.AccessDeniedException: Access is denied
      at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:83) ~[AffirmativeBased.class:3.2.4.RELEASE]
      at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:206) ~[AbstractSecurityInterceptor.class:3.2.4.RELEASE]
      at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115) ~[FilterSecurityInterceptor.class:3.2.4.RELEASE]
      at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84) ~[FilterSecurityInterceptor.class:3.2.4.RELEASE]
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
      at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) [ExceptionTranslationFilter.class:3.2.4.RELEASE]
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
      at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) [ExceptionTranslationFilter.class:3.2.4.RELEASE]
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
      at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103) [SessionManagementFilter.class:3.2.4.RELEASE]
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
      at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113) [AnonymousAuthenticationFilter.class:3.2.4.RELEASE]
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
      at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154) [SecurityContextHolderAwareRequestFilter.class:3.2.4.RELEASE]
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
      at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) [RequestCacheAwareFilter.class:3.2.4.RELEASE]
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
      at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199) [AbstractAuthenticationProcessingFilter.class:3.2.4.RELEASE]
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
      at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110) [LogoutFilter.class:3.2.4.RELEASE]
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
      at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57) [HeaderWriterFilter.class:3.2.4.RELEASE]
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [OncePerRequestFilter.class:4.0.5.RELEASE]
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
      at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) [SecurityContextPersistenceFilter.class:3.2.4.RELEASE]
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
      at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50) [WebAsyncManagerIntegrationFilter.class:3.2.4.RELEASE]
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [OncePerRequestFilter.class:4.0.5.RELEASE]
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
      at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) [FilterChainProxy.class:3.2.4.RELEASE]
      at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) [FilterChainProxy.class:3.2.4.RELEASE]
      at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344) [DelegatingFilterProxy.class:4.0.5.RELEASE]
      at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261) [DelegatingFilterProxy.class:4.0.5.RELEASE]
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [catalina.jar:8.0.12]
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.12]
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) [catalina.jar:8.0.12]
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [catalina.jar:8.0.12]
      at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505) [catalina.jar:8.0.12]
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) [catalina.jar:8.0.12]
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [catalina.jar:8.0.12]
      at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610) [catalina.jar:8.0.12]
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [catalina.jar:8.0.12]
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:534) [catalina.jar:8.0.12]
      at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1081) [tomcat-coyote.jar:8.0.12]
      at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658) [tomcat-coyote.jar:8.0.12]
      at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222) [tomcat-coyote.jar:8.0.12]
      at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1566) [tomcat-coyote.jar:8.0.12]
      at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1523) [tomcat-coyote.jar:8.0.12]
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_05]
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_05]
      at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:8.0.12]
      at java.lang.Thread.run(Thread.java:745) [na:1.8.0_05]
  </code></pre>