AuthenticationCredentialsNotFoundException with Basic Authentication with Spring Rest Service - java

I got AuthenticationCredentialsNotFoundException running my Spring Rest Service which should be secured with basic authentication. This leads to HTTP 500 instead of the expected 403.
Anything missing in the configuration?
My Spring security config:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("bill").password("abc123").roles("USER");
}
}
My Spring config:
#Configuration
#ComponentScan(basePackages = {"com.dummy"})
#EnableWebMvc
#Import({MySecurityConfig.class})
public class MySpringConfig extends WebMvcConfigurerAdapter implements WebApplicationInitializer {
#Override
public void onStartup(final ServletContext servletContext) throws ServletException {
final AnnotationConfigWebApplicationContext context = getContext();
servletContext.addListener(new ContextLoaderListener(context));
final ServletRegistration.Dynamic dispatcher = servletContext.addServlet("springDispatcher",
new DispatcherServlet(context));
dispatcher.setLoadOnStartup(0);
dispatcher.addMapping("/");
}
private AnnotationConfigWebApplicationContext getContext() {
final AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(MySpringConfig.class);
return context;
}
}
My secured Controller:
#RestController
#RequestMapping("/dummy")
public class MyController {
#PreAuthorize("hasRole('USER')")
#RequestMapping(method = RequestMethod.POST)
public HttpEntity<?> doSomething() {
return new ResponseEntity<>(HttpStatus.CREATED);
}
}
My failing Test (actual: 500, expected: 403):
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration(classes = MySpringConfig.class)
public class MyControllerTest {
#Autowired
protected WebApplicationContext context;
protected MockMvc mvc;
#Before
public void setUp() throws Exception {
new TestContextManager(getClass()).prepareTestInstance(this);
this.mvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
#Test
public void doDummy_not_authorized_403() throws Exception {
final MockHttpServletResponse response = this.mvc.perform(post("/dummy")).andDo(MockMvcResultHandlers.print()).andReturn().getResponse();
assertThat(response.getStatus(), equalTo(403));
}
}

Related

Spring Boot & OAuth2: Getting ResourceAccessException: I/O error on POST request for "http://localhost:5555/oauth/token": Connection refused: connect

based on this example https://github.com/royclarkson/spring-rest-service-oauth I have modified the source code adding repositories and other rest controllers. The resource and authorization servers are running/configured in the same application.
I have added an endpoint "/api/login" (POST) with request body:
{"usernamme":"foo", "password":"bar"}
I want to get an access token for this user in the service called by the controller. This implementation looks as follows:
Controller
public ResponseEntity<OAuth2AccessToken> login(#RequestBody #Valid final LoginCommand credentials)
throws LoginFailedException, UnexpectedErrorException {
try {
final OAuth2AccessToken token = securityService.authenticate(credentials.getUsername(), credentials.getPassword());
return ResponseEntity.ok(token);
} catch (final InvalidGrantException badCredentialExeption) {
throw new LoginFailedException(badCredentialExeption.getMessage());
} catch (final Exception e) {
throw new UnexpectedErrorException(e.getMessage());
}
}
Service
#Autowired
#Qualifier("OAuth2RestOperations")
private OAuth2RestOperations client;
#Override
public OAuth2AccessToken authenticate(final String username, final String password) {
final ResourceOwnerPasswordResourceDetails resourceDetails = (ResourceOwnerPasswordResourceDetails) client.getResource();
resourceDetails.setUsername(username);
resourceDetails.setPassword(password);
return client.getAccessToken();
}
Rest client config
#Configuration
#Import({ OauthProperties2.class })
#EnableOAuth2Client
public class RestClientConfig {
#Autowired
private OauthProperties2 oauth;
#Bean(name = "OAuth2RestOperations")
public OAuth2RestOperations restTemplate(final OAuth2ClientContext oauth2ClientContext) {
return new OAuth2RestTemplate(resource(), oauth2ClientContext);
}
#Bean
public OAuth2ProtectedResourceDetails resource() {
final ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails();
resource.setAccessTokenUri(oauth.getClient().getAccessTokenUri());
resource.setClientId(oauth.getClient().getClientId());
resource.setClientSecret(oauth.getClient().getClientSecret());
resource.setGrantType(oauth.getClient().getGrantType());
resource.setScope(oauth.getClient().getScope());
return resource;
}
}
The Test
public class SecurityApiControllerTest extends TestBase {
#InjectMocks
private SecurityApiController controller;
#Test
public void loginOK() throws Exception {
final String credentials = FileUtils.readContent("requests/loginOK.json");
// #formatter:off
mvc.perform(post("/api/login")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(credentials))
.andExpect(status().isOk());
// #formatter:on
}
}
TestBase
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#SpringBootTest(classes = Application.class)
public class TestBase {
#Autowired
protected WebApplicationContext context;
#Autowired
protected FilterChainProxy springSecurityFilterChain;
protected MockMvc mvc;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mvc = MockMvcBuilders.webAppContextSetup(context).addFilter(springSecurityFilterChain).build();
}
}
When running the application, I can call the endpoint for example with POSTMAN. During the test I get a connection refused as described in question header. I have tried to figure out the reason why the test is not working. Can anybody give me a hint to solve this issue?
It is so weird. It works since I have changed the TestBase class to:
#RunWith(SpringJUnit4ClassRunner.class)
// #WebAppConfiguration
#ContextConfiguration(classes = Application.class)
#SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)

Can not handle unmapped urls/404 errors in Spring

I want to handle unmapped urls/404 errors in Spring MVC App I have found an example Here SO Answer, I Java Based Configuration and tried in this way
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = { "com.app.controller" })
public class ServletConfigurer extends WebMvcConfigurerAdapter {
private Properties errorResolverProperties;
private Properties errorProperties;
/// Here I'm configuring <beans as mentioned in SO Answer
#Bean
public SimpleUrlHandlerMapping simpleUrlHandlerMapping() {
SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping();
errorResolverProperties = new Properties();
errorProperties = new Properties();
errorProperties.put("/**", pageNotFoundController());
errorResolverProperties.put("mappings", errorProperties);
return simpleUrlHandlerMapping;
}
// this is my Controller
#Bean
public PageNotFoundController pageNotFoundController(){
return new PageNotFoundController();
}
#Bean
public TilesConfigurer tilesConfigurer() {
TilesConfigurer tilesConfigurer = new TilesConfigurer();
tilesConfigurer.setDefinitions("/WEB-INF/tiles_xml/tiles.xml");
return tilesConfigurer;
}
}
My controller is
#Controller
public class PageNotFoundController {
#ExceptionHandler
#ResponseStatus(HttpStatus.NOT_FOUND)
public String handleINFException(PageNotFoundException ex) {
return "error";
}
}
and finally the
public class PageNotFoundException extends RuntimeException {
private static final long serialVersionUID = 1L;
public PageNotFoundException(String message) {
super(message);
}
}
but it always shows the same error page of Apache not the custom/my error page.
UPDATE
public class AppInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext rootContext = getWebApplicationContext();
servletContext.addListener(new ContextLoaderListener(rootContext));
servletContext.setInitParameter("defaultHtmlEscape", "true");
// add the dispatcher servlet and map it to /
DispatcherServlet dispatcherServlet = new DispatcherServlet(rootContext);
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(
"springDispatcher", dispatcherServlet);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
private AnnotationConfigWebApplicationContext getWebApplicationContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation("com.app.config");
return context;
}
}
that is it..
If you want to catch it globally, you need a ControllerAdvice:
#ControllerAdvice
public class ExceptionHandlerController {
public static final String DEFAULT_ERROR_VIEW = "error";
public static final String STATUS_CODE = "404";
public static final String TYPE = "Custom Type";
#ExceptionHandler(value = {NoHandlerFoundException.class})
public ModelAndView defaultErrorHandler(HttpServletRequest request, Exception e) {
ModelAndView mav = new ModelAndView(DEFAULT_ERROR_VIEW);
mav.addObject("timestamp", new Date());
mav.addObject("status", STATUS_CODE);
mav.addObject("type", TYPE);
mav.addObject("message", String.format("The requested url is: %s", request.getRequestURL()));
return mav;
}
}
Now you need to activate, that an Exception is thrown in case of 404:
#Autowired
public void configureDispatcher(DispatcherServlet dispatcherServlet){
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
}
Insert it in any #Configuration annotated class.
That's it!
UPDATE
Change your class to
#Configuration
public class AppInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext rootContext = getWebApplicationContext();
servletContext.addListener(new ContextLoaderListener(rootContext));
servletContext.setInitParameter("defaultHtmlEscape", "true");
}
private AnnotationConfigWebApplicationContext getWebApplicationContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation("com.app.config");
return context;
}
#Autowired
public void configureDispatcher(DispatcherServlet dispatcherServlet){
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
}
}

Why does this token based Spring Security filter not get called?

I am currently working on a project in which I use Angular JS and Spring REST services. These last few days I've been trying to get some security into the system (see my previous post). I'm implementing token based security.
I got the basic stuff working, but the XAuthTokenFilter doesn't get called when requests are being done. I have no idea why, I think it's something very simple that I'm overlooking. The relevant classes:
XAuthTokenFilter (doFilter does not get called each request)
public class XAuthTokenFilter extends GenericFilterBean {
private final static String XAUTH_TOKEN_HEADER_NAME = "x-auth-token";
private UserDetailsService detailsService;
private TokenProvider tokenProvider;
public XAuthTokenFilter(UserDetailsService detailsService, TokenProvider tokenProvider) {
this.detailsService = detailsService;
this.tokenProvider = tokenProvider;
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
try {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String authToken = httpServletRequest.getHeader(XAUTH_TOKEN_HEADER_NAME);
if (StringUtils.hasText(authToken)) {
String username = this.tokenProvider.getUserNameFromToken(authToken);
UserDetails details = this.detailsService.loadUserByUsername(username);
if (this.tokenProvider.validateToken(authToken, details)) {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(details, details.getPassword(), details.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(token);
}
}
filterChain.doFilter(servletRequest, servletResponse);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
XAuthTokenConfigurer
public class XAuthTokenConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private TokenProvider tokenProvider;
private UserDetailsService detailsService;
public XAuthTokenConfigurer(UserDetailsService detailsService, TokenProvider tokenProvider) {
this.detailsService = detailsService;
this.tokenProvider = tokenProvider;
}
#Override
public void configure(HttpSecurity http) throws Exception {
XAuthTokenFilter customFilter = new XAuthTokenFilter(detailsService, tokenProvider);
http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
}
}
SecurityConfiguration
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Inject
private Http401UnauthorizedEntryPoint authenticationEntryPoint;
#Inject
private UserDetailsService userDetailsService;
#Inject
private TokenProvider tokenProvider;
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Inject
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/scripts/**/*.{js,html}");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.csrf()
.disable()
.headers()
.frameOptions()
.disable()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/protected/**").authenticated()
.antMatchers("/api/open/**").permitAll()
.and()
.apply(securityConfigurerAdapter());
}
private XAuthTokenConfigurer securityConfigurerAdapter() {
return new XAuthTokenConfigurer(userDetailsService, tokenProvider);
}
/**
* This allows SpEL support in Spring Data JPA #Query definitions.
*
* See https://spring.io/blog/2014/07/15/spel-support-in-spring-data-jpa-query-definitions
*/
#Bean
EvaluationContextExtension securityExtension() {
return new EvaluationContextExtensionSupport() {
#Override
public String getExtensionId() {
return "security";
}
#Override
public SecurityExpressionRoot getRootObject() {
return new SecurityExpressionRoot(SecurityContextHolder.getContext().getAuthentication()) {};
}
};
}
}
I really have no clue why it doesn't get called, is there something wrong with my url antMatcher() statements?
My Context which might be good to include:
#Configuration
#EnableWebMvc
#Import(AppContext.class) // The context from my backend which is included as a dependency
#ComponentScan("com.example.springsecuritytest")
public class RestContext extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
WebAppInitializer
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
//RootContext
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(RestContext.class);
// Add RootContext using ContextLoaderListener
servletContext.addListener(new ContextLoaderListener(rootContext));
// Registering and mapping dispatcher servlet
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(rootContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
Please check out this git repo. I have prepared a very basic setup that test security with and without a tokenAuthenticationFilter. The filter implementation is just a mock, setting a valid Authentication whenever the header is present, regardless of its value. Please also note the two application WebApplicationInitializers, which are Servlet 3.0 conformant and are configuring the Servlet container programmatically (instead of web.xml).

JspViewResolver doesn't work in java configuration - based spring applciation

I have only Java-based configuration in Spring Application. I have created user entity and Dao for finding / creating users.
The controller has two GET methods - one for user and one for users list and one POST method - for creating / editing a user.
After running at Tomcat 7 server it gives 404 error and message that 'The requested resource is not available.
Dispatcher servlet is configured in SpringWebAppInitializer.class:
public class SpringWebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
appContext.register(ApplicationContextConfig.class);
servletContext.addListener(new ContextLoaderListener(appContext));
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.register(DispatcherServlet.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("SpringDispatcher", new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
View resolver is defined in ApplicationContextConfig.class:
#Configuration
#ComponentScan("pl.wybornie.entity")
#EnableTransactionManagement
public class ApplicationContextConfig extends WebMvcConfigurerAdapter {
#Bean(name = "viewResolver")
public InternalResourceViewResolver getViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/pages/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
//other configuration beans...
}
Jsp files for userList and userForm are in WebContent project's folder under: /WEB-INF/pages/user/*.jsp
Controllers responsible for geting views are pasted below:
#Controller
#SessionAttributes({"user"})
public class UserController {
#Autowired
private UserDao userDao;
#RequestMapping(value = "/user_list.html", method = RequestMethod.GET)
public String list(Model model, HttpServletRequest request) {
model.addAttribute("userList", userDao.usersList());
return "user/userList";
}
#RequestMapping(value = "/create.html", method = RequestMethod.GET)
public String edit(#RequestParam(value="id", required=false) Long id, Model model) {
User user = userDao.findOrCreate(id);
model.addAttribute("user", user);
return "user/userForm";
}
#RequestMapping(method = RequestMethod.POST)
public String submitForm(#ModelAttribute("user") User user, BindingResult bindingResult, HttpServletRequest request, Model model) {
userDao.saveOrUpdate(user);
return "redirect:user_list.html";
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
Your class should extend WebMvcConfigurerAdapter class.
#Configuration
#ComponentScan("pl.wybornie.entity")
#EnableWebMvc
public class ApplicationContextConfig extends WebMvcConfigurerAdapter{
}

Using Spring Mvc WebApplicationInitializer, ApplicationContextInitializer and ContextLoaderListener

I use java-based Spring Mvc configuration.
I register the Spring dispatcher servlet in the WebApplicationInitializer implementation.
Load Spring ApplicationContext configuration files. Logic of Spring profiles management is implemented in the ApplicationContextInitializer implementation. And it worked fine.
Here are full examples of the original files:
WebApplicationInitializer
public class SpringMvcExampleWebApplicationInitializer implements WebApplicationInitializer {
private static final String DISPATCHER_SERVLET_NAME = "dispatcher";
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
registerDispatcherServlet(servletContext);
registerHiddenHttpMethodFilter(servletContext);
}
private void registerDispatcherServlet(final ServletContext servletContext) {
WebApplicationContext dispatcherContext = createContext(WebMvcContextConfiguration.class, InfrastructureContextConfiguration.class);
DispatcherServlet dispatcherServlet = new DispatcherServlet(dispatcherContext);
dispatcherServlet.setContextInitializers(new SpringMvcExampleProfilesInitializer());
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(DISPATCHER_SERVLET_NAME, dispatcherServlet);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
private WebApplicationContext createContext(final Class<?>... annotatedClasses) {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(annotatedClasses);
return context;
}
private void registerHiddenHttpMethodFilter(ServletContext servletContext) {
FilterRegistration.Dynamic registration = servletContext.addFilter("hiddenHttpMethodFilter", HiddenHttpMethodFilter.class);
registration.addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD),
false, DISPATCHER_SERVLET_NAME);
}
}
SpringMvcExampleProfilesInitializer
public class SpringMvcExampleProfilesInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
#Override
public void initialize(ConfigurableApplicationContext ctx) {
ConfigurableEnvironment environment = ctx.getEnvironment();
List<String> profiles = new ArrayList<String>(getProfiles());
if( profiles == null || profiles.isEmpty() )
{
throw new IllegalArgumentException("Profiles have not been configured");
}
environment.setActiveProfiles(profiles.toArray( new String[0]));
}
//TODO add logic
private Collection<String> getProfiles() {
return Lists.newArrayList("file_based", "test_data");
}
}
InfrastructureContextConfiguration
#Configuration
#ComponentScan(basePackages = {"com.savdev.springmvcexample.repository", "com.savdev.springmvcexample.config"})
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = {"com.savdev.springmvcexample.repository"})
public class InfrastructureContextConfiguration {
#Configuration
#Profile(value = "file_based")
#PropertySource("classpath:/db/config/file_based.properties")
public static class FileBasedConfiguration {
#Inject
private Environment environment;
#Bean
public DataSource dataSource() {
BasicDataSource dataSource = new org.apache.commons.dbcp.BasicDataSource();
dataSource.setDriverClassName(environment.getProperty("jdbc.driver"));
dataSource.setUrl(environment.getProperty("jdbc.url"));
dataSource.setUsername(environment.getProperty("jdbc.username"));
dataSource.setPassword(environment.getProperty("jdbc.password"));
return dataSource;
}
}
#Bean
public SpringLiquibase liquibase(DataSource dataSource) {
SpringLiquibase liquibase = new SpringLiquibase();
liquibase.setDataSource(dataSource);
liquibase.setChangeLog("classpath:/db/liquibase/changelog/db.changelog-master.xml");
liquibase.setDropFirst(true);
return liquibase;
}
Then I added Spring Security context configuration to the application. To use it the DelegatingFilterProxy have to be loaded. I\ve updated the configuration:
Added new method and invoked it in the onStartup:
private void registerSpringSecurityFilterChain(ServletContext servletContext) {
FilterRegistration.Dynamic springSecurityFilterChain = servletContext.addFilter(
BeanIds.SPRING_SECURITY_FILTER_CHAIN,
new DelegatingFilterProxy());
springSecurityFilterChain.addMappingForUrlPatterns(null, false, "/*");
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
...
registerDispatcherServlet(servletContext);
...
registerSpringSecurityFilterChain(servletContext);
}
Now when I try to request any url I'm getting the error:
message No WebApplicationContext found: no ContextLoaderListener registered?
description The server encountered an internal error that prevented it from fulfilling this request.
exception
java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:251)
Ok, I added the following:
private static final Class<?>[] configurationClasses = new Class<?>[]{
WebMvcContextConfiguration.class, InfrastructureContextConfiguration.class};
...
private void registerListener(ServletContext servletContext) {
WebApplicationContext rootContext = createContext(configurationClasses);
servletContext.addListener(new ContextLoaderListener(rootContext));
}
And invoked it from:
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
registerListener(servletContext);
registerDispatcherServlet(servletContext);
registerHiddenHttpMethodFilter(servletContext);
registerSpringSecurityFilterChain(servletContext);
}
The error has gone.
But all beans that depend on Spring profile are not loaded now. Adding the ContextLoaderListener has broken the SpringMvcExampleProfilesInitializer logic.
No qualifying bean of type [javax.sql.DataSource] found for dependency
What can I do to resolve it? Any ideas, please?
Here is the full updated web initializer class:
public class SpringMvcExampleWebApplicationInitializer implements WebApplicationInitializer {
private static final String DISPATCHER_SERVLET_NAME = "dispatcher";
private static final Class<?>[] configurationClasses = new Class<?>[]{
WebMvcContextConfiguration.class, InfrastructureContextConfiguration.class};
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
registerListener(servletContext);
registerDispatcherServlet(servletContext);
registerHiddenHttpMethodFilter(servletContext);
registerSpringSecurityFilterChain(servletContext);
}
private void registerSpringSecurityFilterChain(ServletContext servletContext) {
FilterRegistration.Dynamic springSecurityFilterChain = servletContext.addFilter(
BeanIds.SPRING_SECURITY_FILTER_CHAIN,
new DelegatingFilterProxy());
springSecurityFilterChain.addMappingForUrlPatterns(null, false, "/*");
}
private void registerDispatcherServlet(final ServletContext servletContext) {
WebApplicationContext dispatcherContext = createContext(WebMvcContextConfiguration.class, InfrastructureContextConfiguration.class);
DispatcherServlet dispatcherServlet = new DispatcherServlet(dispatcherContext);
dispatcherServlet.setContextInitializers(new SpringMvcExampleProfilesInitializer());
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(DISPATCHER_SERVLET_NAME, dispatcherServlet);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
private WebApplicationContext createContext(final Class<?>... annotatedClasses) {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(annotatedClasses);
// context.refresh();
return context;
}
private void registerListener(ServletContext servletContext) {
WebApplicationContext rootContext = createContext(configurationClasses);
servletContext.addListener(new ContextLoaderListener(rootContext));
// servletContext.addListener(new RequestContextListener());
}
private void registerHiddenHttpMethodFilter(ServletContext servletContext) {
FilterRegistration.Dynamic registration = servletContext.addFilter("hiddenHttpMethodFilter", HiddenHttpMethodFilter.class);
registration.addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD),
false, DISPATCHER_SERVLET_NAME);
}
}
As M.Deinum recommended I set the profiles initialier to the ServletContext, instead of setting it to DispatcherServlet. Here is the updated configuration:
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
configureServletContext( servletContext );
registerListener(servletContext);
registerDispatcherServlet(servletContext);
...
}
private void configureServletContext(ServletContext servletContext) {
String initializerClasses = servletContext.getInitParameter(ContextLoader.CONTEXT_INITIALIZER_CLASSES_PARAM);
String profilesInitClassName = SpringMvcExampleProfilesInitializer.class.getName();
if (StringUtils.hasText(initializerClasses)) {
initializerClasses += " " + profilesInitClassName;
}
else {
initializerClasses = profilesInitClassName;
}
servletContext.setInitParameter(ContextLoader.CONTEXT_INITIALIZER_CLASSES_PARAM, initializerClasses);
}

Categories