0

This is my project structure:

Project structure

and this is Spring root config:

@EnableWebMvc
@Configuration
@ComponentScan({ "com.rgh.*" })
@EnableTransactionManagement
@Import({ SpringSecurityConfig.class })
public class SpringWebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/assets/**").addResourceLocations("/assets/");
    }

    // Start localization configs
    @Bean
    public MessageSource messageSource() {
        final ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename("classpath:messages");
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }

    @Bean
    public LocaleResolver localeResolver() {
        CookieLocaleResolver localeResolver = new CookieLocaleResolver();
        localeResolver.setDefaultLocale(new Locale("fa"));
        return localeResolver;
    }

    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
        localeChangeInterceptor.setParamName("lang");
        return localeChangeInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeChangeInterceptor());
    }
    // End localization configs

    @Bean
    public SessionFactory sessionFactory() {
        LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder(dataSource());
        builder.scanPackages("com.rgh.*.model").addProperties(getHibernateProperties());
        return builder.buildSessionFactory();
    }

    private Properties getHibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.format.sql", "false");
        properties.put("hibernate.show.sql", "true");
        properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
        properties.put("hibernate.hbm2ddl.auto", "update");
        return properties;
    }

    @Bean(name = "dataSource")
    public BasicDataSource dataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/framework");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        return dataSource;
    }

    @Bean
    public HibernateTransactionManager txManager() {
        return new HibernateTransactionManager(sessionFactory());
    }

    @Bean
    public InternalResourceViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/view/");
        viewResolver.setSuffix(".jsp");

        return viewResolver;
    }
}

but when is start the application with localhost:8080, spring does not recognize default locale that set to localeResolver.setDefaultLocale(new Locale("fa")); and load the page with en_US locale and also when i call the page with localhost:8080/?lang=de it load pages with en_US locale again.

Thanks for any idea.

UPDATE

public class SpringWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringWebConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return null;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

UPDATE2

These are my new configurations, by default default locale is en_US and messages files does not be loaded, i should open the login page, and enter invalid username and password then press submit, then the messsages_fa.properties will be loaded and locale changed to fa!!!

public class SpringWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { SpringWebConfig.class };
    }

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { SpringSecurityConfig.class, SpringPersistanceConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/", "/rest/*" };
    }
}

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    @Qualifier("userDetailsService")
    UserDetailsService  userDetailsService;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.headers().frameOptions().sameOrigin();
        http.authorizeRequests().antMatchers("/assets/**").permitAll().antMatchers("/admin/**").access("hasRole('ROLE_USER')").and().formLogin().loginPage("/login").failureUrl("/login?error").defaultSuccessUrl("/admin").usernameParameter("username").passwordParameter("password").and().logout().logoutSuccessUrl("/login?logout");
    }
}

@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = { "com.rgh.*" }, excludeFilters = { @Filter(Controller.class) })
public class SpringPersistanceConfig {

    @Bean
    public SessionFactory sessionFactory() {
        LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder(dataSource());
        builder.scanPackages("com.rgh.*.model").addProperties(getHibernateProperties());
        return builder.buildSessionFactory();
    }

    private Properties getHibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.format.sql", "false");
        properties.put("hibernate.show.sql", "true");
        properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
        properties.put("hibernate.hbm2ddl.auto", "update");
        return properties;
    }

    @Bean(name = "dataSource")
    public BasicDataSource dataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/framework");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        return dataSource;
    }

    @Bean
    public HibernateTransactionManager txManager() {
        return new HibernateTransactionManager(sessionFactory());
    }
}

@Controller
public class BaseController {

    @RequestMapping(value = "/admin**", method = RequestMethod.GET)
    public ModelAndView adminPage() {
        ModelAndView model = new ModelAndView();
        model.setViewName("/panel/admin");
        return model;
    }

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public ModelAndView login() {
        ModelAndView model = new ModelAndView();
        model.setViewName("/panel/login");

        return model;
    }
}
Rasool Ghafari
  • 4,128
  • 7
  • 44
  • 71

1 Answers1

2

The problem is that you are loading everything in the root context and some of the beans aren't detected that way. Next to that you should really split your configurations. Create a web, security and persistence configuration and load the security and persistence in the root config and the web in the dispatcher servlet.

@Configuration
@EnableTransactionManagement
@ComponentScan({ "com.rgh"}, excludeFilters = {
    @Filter(org.springframework.stereotype.Controller.class)
})
public class PersistenceConfiguration {

    // Hibernate, transaction manager, datasource and messageSource go here

}

Then a web configuration

@EnableWebMvc
@Configuration
@ComponentScan({ "com.rgh"}, includeFilters = {
    @Filter(org.springframework.stereotype.Controller.class)
}, useDefaultFilters=false )
public class SpringWebConfig extends WebMvcConfigurerAdapter {

    /// web related things like view resolvers, controller, interceptors go here

}

Then in your bootstrap class load the correct configuration classes.

public class SpringWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringWebSecurity.class, PersistenceConfiguration.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { SpringWebConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

Now you have split your configuration and everything is loaded by the correct one. The includeFilter and excludeFilter as well as the useDefaultFilters properties on the component-scan are important here to avoid duplicating beans. If you don't all your beans would be loaded twice once by the root and once by the dispatcherservlet.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • It doesn't work completely, when i open the login form that some of messages are used in it, the default locale is set to `en_US`, but i set it to`fa` in `SpringWebConfig`. now, when enter invalid username and password and then press login button to submit form, when the login page refreshed, locale set `fa`!!!! – Rasool Ghafari Mar 11 '16 at 19:15