Spring 4.0.0 version with spring security framework 3.2.3 added using maven.
Problem is that the pages which are supposed to be authenticated are not throwing any login form and rather showing the content.
web.xml -
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>SpringMvcJdbcTemplate</display-name>
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>SpringDispatcher</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>com.wiselife.in</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringDispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
WebMVCConfiguration (annotations based)
#Configuration
#ComponentScan(basePackages="com.wiselife.in")
#EnableWebMvc
#Import({ AppSecurityConfig.class })
public class MvcConfiguration extends WebMvcConfigurerAdapter{
#Bean
public ViewResolver getViewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
/*public #Bean TilesViewResolver tilesViewResolver() {
return new TilesViewResolver();
}
public #Bean TilesConfigurer tilesConfigurer() {
TilesConfigurer ret = new TilesConfigurer();
ret.setDefinitions(new String[] { "/WEB-INF/tiles-defs.xml" });
return ret;
}*/
#Bean
public DataSource getDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/contactdb");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
#Bean
public ContactDAO getContactDAO() {
return new ContactDAOImpl(getDataSource());
}
AppSecurityConfig: -
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true)
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication().withUser("tom").password("123456")
.roles("USER");
auth.inMemoryAuthentication().withUser("bill").password("123456")
.roles("ADMIN");
auth.inMemoryAuthentication().withUser("james").password("123456")
.roles("SUPERADMIN");
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("tom").password("123456").roles("USER").and()
.withUser("bill").password("123456").roles("USER", "ADMIN").and()
.withUser("james").password("123456").roles("USER", "ADMIN", "SUPERADMIN");
}
#Bean #Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/protected/**")
.access("hasRole('ROLE_ADMIN')")
.antMatchers("/confidential/**")
.access("hasRole('ROLE_SUPERADMIN')").and().formLogin();
}
Main Controller:-
#Controller
public class HomeController {
#Autowired
private ContactDAO contactDAO;
#RequestMapping(value = "/")
public ModelAndView listContact(ModelAndView model) throws IOException {
List<Contact> listContact = contactDAO.list();
model.addObject("listContact", listContact);
model.setViewName("home");
return model;
}
#RequestMapping(value = "/newContact", method = RequestMethod.GET)
public ModelAndView newContact(ModelAndView model) {
Contact newContact = new Contact();
model.addObject("contact", newContact);
model.setViewName("ContactForm");
return model;
}
#RequestMapping(value = "/saveContact", method = RequestMethod.POST)
public ModelAndView saveContact(#ModelAttribute Contact contact) {
contactDAO.saveOrUpdate(contact);
return new ModelAndView("redirect:/");
}
#RequestMapping(value = "/deleteContact", method = RequestMethod.GET)
public ModelAndView deleteContact(HttpServletRequest request) {
int contactId = Integer.parseInt(request.getParameter("id"));
contactDAO.delete(contactId);
return new ModelAndView("redirect:/");
}
#RequestMapping(value = "/protected**", method = RequestMethod.GET)
public ModelAndView protectedPage() {
ModelAndView model = new ModelAndView();
model.addObject("title", "Spring Security 3.2.3 Hello World");
model.addObject("message",
"This is protected page - Only for Administrators !");
model.setViewName("protected");
return model;
}
#RequestMapping(value = "/confidential**", method = RequestMethod.GET)
public ModelAndView superAdminPage() {
ModelAndView model = new ModelAndView();
model.addObject("title", "Spring Security 3.2.3 Hello World");
model.addObject("message",
"This is confidential page - Need Super Admin Role !");
model.setViewName("protected");
return model;
}
#RequestMapping(value = "/editContact", method = RequestMethod.GET)
public ModelAndView editContact(HttpServletRequest request) {
int contactId = Integer.parseInt(request.getParameter("id"));
Contact contact = contactDAO.get(contactId);
ModelAndView model = new ModelAndView("ContactForm");
model.addObject("contact", contact);
return model;
}
Any help here will be really appreciable.
AJ
There is a very nasty pitfall with Spring's web security configuration: you must either annotate the class with #EnableWebSecurity or make it extends WebSecurityConfigurerAdapter. When you have both, then the defaults from #EnableWebSecurity take precedence and your custom configuration is silently ignored. Therefore I expect your application to start behaving well when you remove the annotation.
Sice you don't seem to be using the per-controller-method security annotations, I would suggest also removing the #EnableGlobalMethodSecurity(securedEnabled = true) annotation, which is used only to make that work. In that case you don't need the configureGlobal method. It may even be in collision with your configure method.
Related
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 {
}
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 think my configuration is ok but I keep getting the same error "Did not find handler method".
The error:
10:55:46.284 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Looking up handler method for path /WEB-INF/views/html/products/list.html
10:55:46.285 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Did not find handler method for [/WEB-INF/views/html/products/list.html]
10:55:46.285 [http-nio-8080-exec-3] WARN org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/store/WEB-INF/views/html/products/list.html] in DispatcherServlet with name 'spring-web'
10:55:46.285 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.DispatcherServlet - Successfully completed request
My web.xml is as below:
<servlet>
<servlet-name>spring-web</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-web</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
My spring-web-servlet.xml
<context:component-scan base-package="com.ecommerce.config" />
My SprinWebConfig.java
#EnableWebMvc
#Configuration
#ComponentScan({ "com.ecommerce.web", "com.ecommerce.service", "com.ecommerce.dao", "com.ecommerce.exception", "com.ecommerce.validator" })
public class SpringWebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/html/");
viewResolver.setSuffix(".html");
return viewResolver;
}
#Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource rb = new ResourceBundleMessageSource();
rb.setBasenames(new String[] {"messages/messages", "messages/validation"});
return rb;
}
}
ProductController.java
#Controller
public class ProductController {
private final Logger logger = LoggerFactory.getLogger(ProductController.class);
#GetMapping("/")
public String index(Model model) {
logger.debug("index()");
return "redirect:/products";
}
#GetMapping("/products")
public String showAllProducts(Model model) {
logger.debug("showAllProducts()");
//Here I'm constructing a list named products
model.addAttribute("products", products);
return "products/list";
}
}
So, I can't see where is my problem. Can you help please? thanks
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.
I wrote a simple controller for uploading files:
#RestEndpoint
public class ImageController {
#Autowired
GridFsTemplate mTemplate;
#RequestMapping(value = "images", method = RequestMethod.POST)
public #ResponseBody String testPhoto(#RequestParam String name, #RequestParam String directory, #RequestParam MultipartFile file) throws IOException {
if(!file.isEmpty()){
final byte[] bytes = file.getBytes();
InputStream inputStream = new ByteArrayInputStream(bytes);
mTemplate.store(inputStream, "name");
return "uploaded photo";
}
return "failed";
}
}
#RestEndpoint annotation is:
#Target({ ElementType.TYPE })
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Controller
public #interface RestEndpoint
{
String value() default "";
}
My ContextCOnfiguration class is:
#Configuration
#EnableWebMvc
#ComponentScan(
basePackages = "com.questter.site",
useDefaultFilters = false,
includeFilters =
#ComponentScan.Filter({RestEndpoint.class, RestEndpointAdvice.class})
)
public class RestServletContextConfiguration extends WebMvcConfigurerAdapter {
#Bean
public CommonsMultipartResolver multiPartResolver(){
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
return resolver;
}
...
}
--- UPDATED ---
web.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<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">
<display-name>Spring Application</display-name>
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspf</url-pattern>
<page-encoding>UTF-8</page-encoding>
<scripting-invalid>true</scripting-invalid>
<include-prelude>/WEB-INF/jsp/base.jspf</include-prelude>
<trim-directive-whitespaces>true</trim-directive-whitespaces>
<default-content-type>text/html</default-content-type>
</jsp-property-group>
</jsp-config>
<!--<context-param>-->
<!--<param-name>spring.profiles.active</param-name>-->
<!--<param-value>development</param-value>-->
<!--</context-param>-->
<session-config>
<session-timeout>30</session-timeout>
<cookie-config>
<http-only>true</http-only>
</cookie-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>
<distributable />
</web-app>
---- UPDATED ----
public class Bootstrap implements WebApplicationInitializer
{
#Override
public void onStartup(ServletContext container) throws ServletException
{
container.getServletRegistration("default").addMapping("/resource/*");
AnnotationConfigWebApplicationContext rootContext =
new AnnotationConfigWebApplicationContext();
rootContext.register(RootContextConfiguration.class);
container.addListener(new ContextLoaderListener(rootContext));
AnnotationConfigWebApplicationContext webContext =
new AnnotationConfigWebApplicationContext();
webContext.register(WebServletContextConfiguration.class);
ServletRegistration.Dynamic dispatcher = container.addServlet(
"springWebDispatcher", new DispatcherServlet(webContext)
);
dispatcher.setLoadOnStartup(1);
dispatcher.setMultipartConfig(new MultipartConfigElement(
null, 20_971_520L, 41_943_040L, 512_000
));
dispatcher.addMapping("/");
AnnotationConfigWebApplicationContext restContext =
new AnnotationConfigWebApplicationContext();
restContext.register(RestServletContextConfiguration.class);
DispatcherServlet servlet = new DispatcherServlet(restContext);
servlet.setDispatchOptionsRequest(true);
dispatcher = container.addServlet(
"springRestDispatcher", servlet
);
dispatcher.setLoadOnStartup(2);
dispatcher.addMapping("/rest/*");
rootContext.refresh();
DbBootstrap dbBootstrap = rootContext.getBean(DbBootstrap.class);
dbBootstrap.init();
}
}
When perfoming a post request (using postman) i'm getting:
HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalArgumentException:Expected MultipartHttpServletRequest: is a MultipartResolver configured
I've looked over some similar questions over stackoverflow but none of the answers helped
me.
Spring version is: 4.0.4
Any help will be greatly appreciated (with a thumbs up of course).
Thanks
I don't know why they did this, but the MultipartResolver bean in the context needs to be named multipartResolver. Rename your #Bean method to
public CommonsMultipartResolver multipartResolver(){ // lowercase 'P'
Or give it the name explicitly
#Bean(name = "multipartResolver")
public CommonsMultipartResolver canBeCalledAnything(){
allowCasualMultipartParsing="true"
on context tag inside context.xml, it's work for me
It is straight forward from the exception that no multi-part configuration is found. Though you have provided multipartResolver bean.
The problem is that while specifying the MultipartFilter before the Spring Security filter, It tries to get the multipartResolver bean but can't find it. Because it expect the bean name/id as filterMultipartResolver instead of multipartResolver.
Do yourself a favor. Please change the bean configuration like following -
#Bean
public CommonsMultipartResolver filterMultipartResolver(){
CommonsMultipartResolver resolver = new
CommonsMultipartResolver();
return resolver;
}
or
#Bean(name = "filterMultipartResolver")
public CommonsMultipartResolver multiPartResolver(){
CommonsMultipartResolver resolver = new
CommonsMultipartResolver();
return resolver;
}
The answer by R. Ali Ashik worked for me.
Following is the relevant part of pom.xml of the project that I am working on:
<properties>
<springframework.version>5.0.2.RELEASE</springframework.version>
<springsecurity.version>5.0.0.RELEASE</springsecurity.version>
<hibernate.version>5.2.17.Final</hibernate.version>
<mysql.connector.version>8.0.11</mysql.connector.version>
Since, I have a custom login page with persistent authentication setup, I also needed to have the following:
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
#Override
protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
insertFilters(servletContext, new MultipartFilter());
}
}
But the actual clincher was this as pointed out by R. Ali Ashik:
#Bean(name = "filterMultipartResolver")
public CommonsMultipartResolver multiPartResolver(){
CommonsMultipartResolver resolver = new
CommonsMultipartResolver();
return resolver;
}
The relevant reference material in the context is this:
Class MultipartFilter
And the relevant text is as follows:
Looks up the MultipartResolver in Spring's root web application context. Supports a "multipartResolverBeanName" filter init-param in web.xml; the default bean name is "filterMultipartResolver". Looks up the MultipartResolver on each request, to avoid initialization order issues (when using ContextLoaderServlet, the root application context will get initialized after this filter).