I Use spring 5.0.7.RELEASE and I need to add basic authentication for my spring application and this is a pretty old application. That is why it uses the old way of registering the config classes. I have added the SecurityConfig class and imported it in the SpringMvcConfig as shown below
#Configuration
#EnableWebMvc
#ComponentScan( basePackages = {
"com.test" },
excludeFilters = {
#ComponentScan.Filter( Configuration.class )
} )
#ImportResource("classpath:/spring-context.xml")
#EnableSwagger2
#Import({SwaggerConfig.class, SecurityConfig.class})
public class SpringMvcConfig extends WebMvcConfigurationSupport {
#Autowired private ApplicationContext applicationContext;
private static final String[] RESOURCE_BUNDLES = new String[] { "MessageResources" };
private static final String[] YAML_RESOURCE_BUNDLES = new String[] { "messages" };
/**
* Configures the Jackson object mapper
*/
#Bean( name = "objectMapper" )
public ObjectMapper getObjectMapper( JacksonService jacksonService ) {
return jacksonService.getObjectMapper();
}
/**
* Configures the ApplicationContextProvider
*/
#Bean( name = "applicationContextProvider" )
public ApplicationContextProvider getApplicationContextProvider() {
return new ApplicationContextProvider();
}
}
and here is the web.xml
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.test.SpringMvcConfig</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- Spring Security Configuration -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
and here is my SecurityConfig.java
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests().anyRequest().authenticated()
.and()
.httpBasic();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication()
.withUser("test")
.password("testpwd")
.roles("USER");
}
}
I get a 403 forbidden The server understood the request but refuses to authorize it. I also added
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
}
Related
I am trying to create a simple app with Spring and Spring Security.
When I hit the default localhost:8080/oauth/token endpoint with username and password in the body I expect to get a token or an error if a given user does not exist.
I get 401 though. Why is that?
Here are some of my config files:
#EnableResourceServer
#Configuration
public static class ResourceServer extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(PUBLIC_URIS).permitAll();
}
}
#EnableAuthorizationServer
#Configuration
public static class AuthorizationServer extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManagerBean;
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient(CLIENT_ID)
.authorizedGrantTypes(GRANT_TYPE)
.scopes(SCOPE);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManagerBean);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients();
}
Security class:
#Configuration
#EnableWebSecurity
public class Security extends WebSecurityConfigurerAdapter {
#Autowired
private UserService usersService;
private PasswordEncoder passwordEncoder = new StandardPasswordEncoder();
#Bean
public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
return new SecurityEvaluationContextExtension();
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(usersService).passwordEncoder(passwordEncoder);
}
}
And web.xml:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>CORS</filter-name>
<filter-class>pl.kabat.security.configuration.SimpleCORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
From the HTTP specs:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401
"The HTTP 401 Unauthorized client error status response code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource."
In other words, what you're getting is exactly an authentication error.
I am new to Spring and trying to create authentication for RESTful API using Spring. I am getting the following error, how can I resolve this?
StackTrace:
Error creating bean with name 'webConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.setAuthenticationConfiguration(org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>springrest</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springrest</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
WebConfig.java
#Configuration
#EnableWebMvc
#ComponentScan("com.base")
public class WebConfig extends WebSecurityConfigurerAdapter{
#Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
#Autowired
private MySavedRequestAwareAuthenticationSuccessHandler authenticationSuccessHandler;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().
withUser("temporary").password("temporary").roles("ADMIN").and().
withUser("user").password("userPass").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.authorizeRequests()
.antMatchers("/api/foos").authenticated()
.and()
.formLogin()
.successHandler(authenticationSuccessHandler)
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and()
.logout();
}
}
MySavedRequestAwareAuthenticationSuccessHandler.java
#Component
public class MySavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
private RequestCache requestCache = new HttpSessionRequestCache();
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws ServletException, IOException {
SavedRequest savedRequest = requestCache.getRequest(request, response);
if (savedRequest == null) {
clearAuthenticationAttributes(request);
return;
}
String targetUrlParam = getTargetUrlParameter();
if (isAlwaysUseDefaultTargetUrl()
|| (targetUrlParam != null && StringUtils.hasText(request.getParameter(targetUrlParam)))) {
requestCache.removeRequest(request, response);
clearAuthenticationAttributes(request);
return;
}
clearAuthenticationAttributes(request);
}
public void setRequestCache(RequestCache requestCache) {
this.requestCache = requestCache;
}
}
Use #EnableWebSecurity for web security configuration
Split the WebConfig from the WebSecurityConfig to different classes.
In my web.xml I have two different dispatcher servlets, one of them has all beans from root context, second dispatcher servlet has another authenticationManager.
as sayed:
In the Web MVC framework, each DispatcherServlet
has its own WebApplicationContext, which inherits all the beans already defined in the root
WebApplicationContext. The root WebApplicationContext should contain all the infrastructure
beans that should be shared between your other contexts and Servlet instances. These inherited beans
can be overridden in the servlet-specific scope, and you can define new scope-specific beans local to
a given Servlet instance.
So my new authenticationManager must override the same bean from root context. This authenticationManager has another daoAuthenticationProvider, which has another userDetailsService. But when I want to log in in system from path for second dispathcer servlet, spring uses authenticationManager from root context.
It is web.xml:
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>ua.translate.AppConfig</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>ua.translate.AppConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>adminDispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>ua.admin.AdminConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>adminDispatcher</servlet-name>
<url-pattern>/bulbular/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
It is AdminConfig.class:
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = {"ua.admin"})
#EnableTransactionManagement
#EnableAspectJAutoProxy(proxyTargetClass = true)
public class AdminConfig extends WebMvcConfigurerAdapter{
}
It is WebSecurityConfigurerAdapter implementation, which is located in ua.admin package and have new authenticationManager:
#EnableWebSecurity
#Configuration
#ComponentScan(basePackages = {"ua.translate.handler","ua.translate.service.impl"})
#Order(1)
public class AdminSecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
protected CustomSuccessHandler customSuccessHandler;
#Autowired
#Qualifier("customAccessDeniedHandler")
protected AccessDeniedHandler accessDeniedHandler;
#Autowired
#Qualifier("adminDetailsService")
private UserDetailsService uds;
#Override
public void configure(WebSecurity web){
web
.ignoring()
.antMatchers(new String[]{"/resources/**"});
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/bulbular/**")
.authorizeRequests()
.antMatchers("/bulbular/login").permitAll()
.anyRequest().hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/bulbular/login")
.permitAll()
.successHandler(customSuccessHandler)
.failureUrl("/bulbular/login?error")
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/j_spring_security_check")
.and()
.logout().deleteCookies("JSESSIONID")
.logoutUrl("/bulbular/logout")
.logoutSuccessUrl("/bulbular/login?logout")
.and()
.csrf()
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler);
}
#Bean
public AuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider impl = new DaoAuthenticationProvider();
impl.setUserDetailsService(uds);
impl.setPasswordEncoder(bcryptEncoder());
impl.setHideUserNotFoundExceptions(false);
return impl;
}
#Bean
public PasswordEncoder bcryptEncoder(){
return new BCryptPasswordEncoder();
}
#Bean(name = "authenticationManager")
public ProviderManager getProviderManager(){
List<AuthenticationProvider> providers = new ArrayList<>();
providers.add(daoAuthenticationProvider());
ProviderManager providerManager = new ProviderManager(providers);
return providerManager;
}
This class is WebSecurityConfigurer implementation in root context, it is base class for two another classes:
#EnableWebSecurity
#ComponentScan(basePackages = {"ua.translate"})
#Order(99)
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
protected CustomSuccessHandler customSuccessHandler;
#Autowired
#Qualifier("customAccessDeniedHandler")
protected AccessDeniedHandler accessDeniedHandler;
#Autowired
protected PersistentTokenRepository tokenRepository;
#Autowired
#Qualifier("userDetailsServiceImpl")
protected UserDetailsService uds;
#Override
public void configure(WebSecurity web){
web
.ignoring()
.antMatchers(new String[]{"/resources/**"});
}
#Bean
public AuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider impl = new DaoAuthenticationProvider();
impl.setUserDetailsService(uds);
impl.setPasswordEncoder(bcryptEncoder());
impl.setHideUserNotFoundExceptions(false);
return impl;
}
#Bean(name = "authenticationManager")
public ProviderManager getProviderManager(){
List<AuthenticationProvider> providers = new ArrayList<>();
providers.add(daoAuthenticationProvider());
ProviderManager providerManager = new ProviderManager(providers);
return providerManager;
}
#Bean
public PasswordEncoder bcryptEncoder(){
return new BCryptPasswordEncoder();
}
There are two subclasses, which is located in root context:
#Configuration
#EnableWebSecurity
public class SecurityConfig {
#Configuration
#Order(3)
public static class AppSecurityConfigClient extends AppSecurityConfig{
#Override
public void configure(WebSecurity web){
web
.ignoring()
.antMatchers(new String[]{"/resources/**"});
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/client/registration*").anonymous()
.antMatchers("/index","/translators","/orders","/client/login*","/client/confirmation").permitAll()
.antMatchers("/client/**").hasRole("CLIENT")
.and()
.formLogin()
.loginPage("/client/login")
.permitAll()
.successHandler(customSuccessHandler)
.failureUrl("/client/login?error")
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/j_spring_security_check")
.and()
.logout().deleteCookies("JSESSIONID")
.logoutUrl("/client/logout")
.logoutSuccessUrl("/client/login?logout")
.and()
/*!!!!Доделать saved request url!!!!*/
.rememberMe().tokenRepository(tokenRepository)
.tokenValiditySeconds(86400)
.and()
.csrf()
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler);
}
}
#Configuration
#Order(2)
public static class AppSecurityConfigTranslator extends AppSecurityConfig {
#Override
public void configure(WebSecurity web){
web
.ignoring()
.antMatchers(new String[]{"/resources/**"});
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/translator/**")
.authorizeRequests()
.antMatchers("/translator/registration*").anonymous()
.antMatchers("/translator/index","/translator/login*","/translator/confirmation").permitAll()
.antMatchers("/translator/**").hasRole("TRANSLATOR")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/translator/login")
.permitAll()
.successHandler(customSuccessHandler)
.failureUrl("/translator/login?error")
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/j_spring_security_check")
.and()
.logout().deleteCookies("JSESSIONID")
.logoutUrl("/translator/logout")
.logoutSuccessUrl("/translator/login?logout")
.and()
/**
* Доделать saved request url!!!
*/
.rememberMe().tokenRepository(tokenRepository)
.tokenValiditySeconds(86400)
.and()
.csrf()
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.and()
.userDetailsService(uds);
}
}
}
So, adminDispatcher servlet uses ua.admin.AdminConfig, which in turn scan ua.admin package, and find WebSecurityConfigurerAdapter implementation with second authenticationManager implementation.
/bulbular/ - it is path for this dispathcer servlet, and path for http configuration in WebSecurityConfigurerAdapter implementation. But when I want to log in from /bulbular/login page, spring uses implementatation from SecurityConfig.class - class from root context. Help please!!!!
I'm trying to convert my spring xml configuration to a java type configuration. So far I have gotten most things working but I am struggling with configuring the security of the application. I currently get the following error when trying to access a secured path.
Request processing failed; nested exception is org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
I assume I have missed something important but I don't understand what it is. Any help is appreciated.
Here are my configuration files.
SecurityConfiguration.java
#Configuration
#EnableWebSecurity
#Order(1)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
#Autowired
private NegotiateSecurityFilterEntryPoint authenticationEntryPoint;
#Autowired
private NegotiateSecurityFilter securityFilter;
#Bean
public WindowsAuthProviderImpl waffleAuthProvider(){
return new WindowsAuthProviderImpl();
}
#Bean(name="negotiateSecurityFilterProvider")
#Autowired
public NegotiateSecurityFilterProvider negotiateSecurityFilterProvider(
final WindowsAuthProviderImpl windowsAuthProvider
){
NegotiateSecurityFilterProvider bean = new NegotiateSecurityFilterProvider(windowsAuthProvider);
List<String> protocols = new ArrayList<>();
protocols.add("Negotiate");
bean.setProtocols(protocols);
return bean;
}
#Bean
public BasicSecurityFilterProvider basicSecurityFilterProvider(final WindowsAuthProviderImpl waffleAuthProvider){
return new BasicSecurityFilterProvider(waffleAuthProvider);
}
#Bean(name="waffleSecurityFilterProviderCollection")
#Autowired
public waffle.servlet.spi.SecurityFilterProviderCollection negotiateSecurityFilterProvider(
final BasicSecurityFilterProvider basicSecurityFilterProvider,
final NegotiateSecurityFilterProvider negotiateSecurityFilterProvider
) {
final List<SecurityFilterProvider> lsp = new ArrayList<>();
lsp.add(negotiateSecurityFilterProvider);
lsp.add(basicSecurityFilterProvider);
return new waffle.servlet.spi.SecurityFilterProviderCollection(lsp.toArray(new SecurityFilterProvider[]{}));
}
#Bean(name="negotiateSecurityFilterEntryPoint")
#Autowired
public waffle.spring.NegotiateSecurityFilterEntryPoint negotiateSecurityFilterEntryPoint(final SecurityFilterProviderCollection securityFilterProviderCollection) {
final waffle.spring.NegotiateSecurityFilterEntryPoint ep = new waffle.spring.NegotiateSecurityFilterEntryPoint();
ep.setProvider(securityFilterProviderCollection);
return ep;
}
#Bean(name="negotiateSecurityFilter")
#Autowired
public waffle.spring.NegotiateSecurityFilter waffleNegotiateSecurityFilter(
final SecurityFilterProviderCollection securityFilterProviderCollection
){
waffle.spring.NegotiateSecurityFilter bean = new waffle.spring.NegotiateSecurityFilter();
bean.setRoleFormat("both");
bean.setPrincipalFormat("fqn");
bean.setAllowGuestLogin(false);
bean.setProvider(securityFilterProviderCollection);
return bean;
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/assets/**");
web.ignoring().antMatchers("/img/**");
web.ignoring().antMatchers("/css/**");
web.ignoring().antMatchers("/partials/**");
web.ignoring().antMatchers("/error/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// A user needs to have the role user and has to be authenticated
Filter customNegotiateSecurityFilter = new CustomPreAuthSecurityFilter();
Filter customPreAuthSecurityFilter = new CustomNegotiateSecurityFilter();
http
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and()
.addFilterBefore(customPreAuthSecurityFilter, BasicAuthenticationFilter.class)
.addFilterAfter(securityFilter, BasicAuthenticationFilter.class)
.addFilterAfter(customNegotiateSecurityFilter, BasicAuthenticationFilter.class)
.authorizeRequests().anyRequest().fullyAuthenticated();
}
}
SpringConfiguration.java
#Configuration
#EnableWebMvc
#EnableScheduling
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, proxyTargetClass = true)
#ComponentScan(basePackages = {"com.realitylabs.spa"})
#PropertySources({
#PropertySource("classpath:app.properties"),
#PropertySource("classpath:general.properties"),
#PropertySource("classpath:log4j.properties"),
#PropertySource("classpath:setup/app.properties"),
#PropertySource("classpath:setup/wro.properties"),
#PropertySource("classpath:setup/jdbc.properties"),
#PropertySource("file:${CONFIG_DIR}/config.properties")
})
public class SpringConfiguration extends WebMvcConfigurerAdapter {
#Autowired
Environment env;
#Autowired
SpringPostConstructHook sp;
private static final int CACHE_PERIOD = 31556926; // one year
// Configure static routes
#Override
public void addResourceHandlers(ResourceHandlerRegistry reg){
reg.addResourceHandler("/img/**")
.addResourceLocations("/assets/img/")
.setCachePeriod(CACHE_PERIOD);
reg.addResourceHandler("/assets/" + env.getProperty("VERSION") + "/**")
.addResourceLocations("/assets/")
.setCachePeriod(CACHE_PERIOD);
}
// Configuration variables
long MAX_UPLOAD_SIZE_IN_BYTES = 5000000;
// WRO4J config (js and css merge and minification)
#Bean
public PropertiesFactoryBean propertiesFactoryBean() {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
Resource wroResource = new ClassPathResource("wro.properties");
propertiesFactoryBean.setLocation(wroResource);
return propertiesFactoryBean;
}
#Bean(name = "wroFilter")
public ConfigurableWroFilter getConfigurableWroFilter() throws IOException {
ConfigurableWroFilter filter = new ConfigurableWroFilter();
filter.setProperties(propertiesFactoryBean().getObject());
return filter;
}
// Post construction print outs
#Bean
public SpringPostConstructHook postConstructHook(){
return new SpringPostConstructHook();
}
// JSP view rendering
#Bean
public InternalResourceViewResolver jspViewResolver() {
InternalResourceViewResolver bean = new InternalResourceViewResolver();
bean.setViewClass(org.springframework.web.servlet.view.JstlView.class);
bean.setPrefix("/WEB-INF/views/");
bean.setSuffix(".jsp");
bean.setOrder(1);
return bean;
}
// Handle file uploads
#Bean(name = "multipartResolver")
public CommonsMultipartResolver getMultipartResolver() {
CommonsMultipartResolver bean = new CommonsMultipartResolver();
bean.setMaxUploadSize(MAX_UPLOAD_SIZE_IN_BYTES);
return bean;
}
// Set specific hibernate config for postgres.
#Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper om = new HibernateAwareObjectMapper();
jsonConverter.setObjectMapper(om);
return jsonConverter;
}
// Poolable connection.
#Bean
public DataSource getDataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc_driverClassName"));
dataSource.setUrl(env.getProperty("jdbc_databaseurl"));
dataSource.setUsername(env.getProperty("jdbc_username"));
dataSource.setPassword(env.getProperty("jdbc_password"));
return dataSource;
}
#Bean
public DataSourceConnectionFactory getDataSourceConnectionFactory() {
DataSourceConnectionFactory bean = new DataSourceConnectionFactory(getDataSource());
return bean;
}
#Bean
public GenericObjectPool getPool() {
GenericObjectPool bean = new GenericObjectPool();
bean.setMaxIdle(30000);
bean.setTimeBetweenEvictionRunsMillis(60000);
return bean;
}
#Bean(name = "poolableConnectionFactory")
public PoolableConnectionFactory getPoolableConnectionFactory() {
PoolableConnectionFactory bean = new PoolableConnectionFactory(getDataSourceConnectionFactory(),getPool(),null,null,false,true);
return bean;
}
#Bean(name = "pooledDS")
#DependsOn({"poolableConnectionFactory"})
public PoolingDataSource getPoolingDataSource() {
PoolingDataSource bean = new PoolingDataSource(getPool());
return bean;
}
// Configure flyway database migrations
#Bean(name = "flyWay")
public Flyway getFlyWay(){
Flyway bean = new Flyway();
bean.setDataSource(getPoolingDataSource());
bean.setLocations("classpath:db/migrations");
bean.setValidateOnMigrate(false);
bean.migrate();
return bean;
}
// Configure hibernate ORM
#Bean(name = "sessionFactory")
#DependsOn({"flyWay"})
public LocalSessionFactoryBean sessionFactory(){
LocalSessionFactoryBean bean = new LocalSessionFactoryBean();
bean.setDataSource(getPoolingDataSource());
bean.setAnnotatedPackages("com.realitylabs.spa.entity");
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("jdbc_dialect"));
hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("hibernate.showSQL"));
hibernateProperties.setProperty("hibernate.jdbc.batch_size", "30");
hibernateProperties.setProperty("hibernate.order_inserts", "true");
hibernateProperties.setProperty("hibernate.order_updates", "true");
hibernateProperties.setProperty("hibernate.connection.pool_size", "30");
bean.setHibernateProperties(hibernateProperties);
bean.setDataSource(getPoolingDataSource());
return bean;
}
// Configure scheduled jobs
#Bean(destroyMethod="shutdown")
public Executor taskExecutor() {
return Executors.newScheduledThreadPool(10);
}
#Scheduled(cron = "0 1 3 * * ?")
public void runSGCSJob() {
SGCSJob job = new SGCSJob();
try {
job.updateEmployees();
} catch (Exception e) {
e.printStackTrace();
}
}
#Scheduled(cron = "0 1 2 * * ?")
public void runLimeJob() {
LimeJob job = new LimeJob();
try {
job.updateCourses();
} catch (Exception e) {
e.printStackTrace();
}
}
// Print config and start jobs post construction
#PostConstruct
#DependsOn("sessionFactory")
public void init() throws SQLException, FileNotFoundException {
sp.printConfiguration();
sp.runJobs();
}
}
CacheConfiguration.java
#Configuration
#EnableCaching
public class CacheConfiguration implements CachingConfigurer {
// Replace the cache manager with ehcache
#Bean
#Override
public org.springframework.cache.CacheManager cacheManager() {
return new EhCacheCacheManager(getEhCacheFactory().getObject());
}
#Override
public CacheResolver cacheResolver() {
return new SimpleCacheResolver();
}
#Override
public KeyGenerator keyGenerator() {
return new SimpleKeyGenerator();
}
#Override
public CacheErrorHandler errorHandler() {
return new SimpleCacheErrorHandler();
}
// Configure ehcache
private EhCacheManagerFactoryBean getEhCacheFactory(){
EhCacheManagerFactoryBean factoryBean = new EhCacheManagerFactoryBean();
factoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
factoryBean.setShared(true);
return factoryBean;
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="MyCareerID" version="3.0">
<display-name>RDS</display-name>
<!-- Configure the session -->
<session-config>
<session-timeout>45</session-timeout>
<tracking-mode>COOKIE</tracking-mode>
</session-config>
<!-- Annotation config -->
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<!-- Context config location -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.realitylabs.spa.springConfig.SpringConfiguration</param-value>
</context-param>
<!-- Force UTF-8 encoding-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Expose the security filter for the tests -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<!-- WRO4J configuration -->
<filter>
<filter-name>WebResourceOptimizer</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>wroFilter</param-value>
</init-param>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<!-- Mapping wro for delivery of combined js files -->
<filter-mapping>
<filter-name>WebResourceOptimizer</filter-name>
<url-pattern>/assets/wro/*</url-pattern>
</filter-mapping>
<!-- Escape html sent to the server -->
<context-param>
<param-name>defaultHtmlEscape</param-name>
<param-value>true</param-value>
</context-param>
<!-- The container running spring -->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Mapping root route to spring -->
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- Mapping error pages -->
<error-page>
<error-code>401</error-code>
<location>/WEB-INF/jsp/error.jsp</location>
</error-page>
</web-app>
I'm not certain if any other files might be interesting please ask if you need anything else.
On my application, I am using spring 3.2, jsf 2.1 and hibernate 4 integration. I want to replace configuration xml files to java config. For that I am focusing on AbstractAnnotationConfigDispatcherServletInitializer and WebMvcConfigurerAdapter section.
web.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name />
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<filter>
<description>generated-persistence-filter</description>
<filter-name>MySQLFilter</filter-name>
<filter-class>
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
</filter-class>
<init-param>
<param-name>entityManagerFactoryBeanName</param-name>
<param-value>MySQL</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MySQLFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.expressionFactory</param-name>
<param-value>com.sun.el.ExpressionFactoryImpl</param-value>
</context-param>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/jsf/login.xhtml</location>
</error-page>
</web-app>
how can implement context-param , welcome-file-list and error-page on javaconfig class.
My javaconfig class is,
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/", "/*", "*.faces", "*.xhtml" };
}
#Override // for representing Faces Serelet context, is it correct?
public void onStartup(ServletContext servletContext)
throws ServletException {
servletContext.addServlet("Faces Servlet", "javax.faces.webapp.FacesServlet");
super.onStartup(servletContext);
}
#Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
OpenEntityManagerInViewFilter openEntityManagerInViewFilter = new OpenEntityManagerInViewFilter();
openEntityManagerInViewFilter.setPersistenceUnitName("MySQL");
return new Filter[] { characterEncodingFilter, openEntityManagerInViewFilter, new org.primefaces.webapp.filter.FileUploadFilter()};
}
}
and
#Configuration
#EnableWebMvc
#Import(DatabaseConfig.class)
#ComponentScan(basePackages = { "com.shiv.ShivCDB.web.jsf", "com.shiv.ShivCDB.service" })
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
registry.addInterceptor(localeChangeInterceptor);
}
#Bean
public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {
SimpleMappingExceptionResolver b = new SimpleMappingExceptionResolver();
Properties mappings = new Properties();
mappings.put("org.springframework.web.servlet.PageNotFound", "p404");
mappings.put("org.springframework.dao.DataAccessException", "dataAccessFailure");
mappings.put("org.springframework.transaction.TransactionException", "dataAccessFailure");
b.setExceptionMappings(mappings);
return b;
}
#Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
cookieLocaleResolver.setDefaultLocale(StringUtils.parseLocaleString("en"));
return cookieLocaleResolver;
}
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:messages/messages", "classpath:messages/validation");
// if true, the key of the message will be displayed if the key is not
// found, instead of throwing a NoSuchMessageException
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding("UTF-8");
// # -1 : never reload, 0 always reload
messageSource.setCacheSeconds(0);
return messageSource;
}
}
you need to register spring ContextLoaderListener in your onStartup method, for xml configuration:
public void onStartup(ServletContext servletContext) {
XmlWebApplicationContext root = new XmlWebApplicationContext
root.setConfigLocation("/WEB-INF/applicationContext.xml")
servletContext.addListener(new ContextLoaderListener(root))
}
for java config:
public void onStartup(ServletContext servletContext) {
AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext
//scan the package of your #Configuration java files
root.scan("org.example.config")
servletContext.addListener(new ContextLoaderListener(root))
}
It looks like there is no annotations or java config support for welcome-file list and error-pages, you still have to define them in web.xml and servlet container will load both web.xml and WebInitializer.
If you want to entirely get rid of web.xml, you can try to implement welcome file and error page in your web framework.
--edit--
I am not familiar with jsf, you can try to add following in method onStartup :
servletContext.setInitParameter("javax.faces.STATE_SAVING_METHOD", "server");
servletContext.setInitParameter("com.sun.faces.expressionFactory", "com.sun.el.ExpressionFactoryImpl");