I know there are some questions about this topic but mine is a little different. I'm trying to include openID authentication into my project developed with Spring, Spring-security and Spring-MVC.
To achieve the openID auth, some clases are necessary: AccessDeniedHandler and UserDetailsService are configured in applicationContext-security.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:security="http://www.springframework.org/schema/security"
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<!-- turn on global security -->
<security:global-method-security secured-annotations="enabled"/>
<bean id="openIdAuthFailureHandler" class="es.institution.dept.security.MyAccessDeniedHandler"/>
<bean id="userDetailsService" class="es.institution.dept.service.impl.UserDetailsServiceImpl"/>
<security:http auto-config="true">
<security:intercept-url pattern="/welcome*" access="ROLE_USER, ROLE_ADMIN" />
<security:intercept-url pattern="/user/*" access="ROLE_USER, ROLE_ADMIN" />
<security:intercept-url pattern="/rest/*" access="ROLE_USER, ROLE_ADMIN" />
<security:intercept-url pattern="/admin/*" access="ROLE_ADMIN" />
<security:logout logout-success-url="/" />
<security:openid-login login-page="/openidLogin" default-target-url="/welcome" authentication-failure-url="/loginfailed" user-service-ref="userDetailsService"/>
<security:access-denied-handler ref="openIdAuthFailureHandler"/>
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:password-encoder hash="md5"/>
<security:jdbc-user-service data-source-ref="dataSource"
users-by-username-query="
SELECT username, password, active as enabled
FROM users WHERE username=?"
authorities-by-username-query="
select ur.username, ur.rolename as authority from users_roles ur
where ur.username=?" />
</security:authentication-provider>
</security:authentication-manager>
</beans>
UserDetailsService is called by Spring when it needs to know user data (username, password, roles...) For this reason, I need to call one of my services (UserService) in UserDetailsService:
public class UserDetailsServiceImpl implements UserDetailsService{
#Autowired
UserService userService;
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
es.institution.dept.model.User user = userService.getUserByUsername("mannuk");
if(user == null)
throw new UsernameNotFoundException("User does not exist");
return new User(user.getUsername(), user.getPassword(), user.isActive(), false, false, false, getGrantedAuthorities(username));
}
public List<GrantedAuthority> getGrantedAuthorities(String username) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (Role role : userService.getAllRoles(username)) {
authorities.add(new SimpleGrantedAuthority(role.getRoleName()));
}
return authorities;
}
}
I tried two options:
1)Define #Service annotation in UserDetailsService which throws an Exception during the start up. It says that UserDetails bean does not exist (it is necessary in applicationSecurity-context.xml)
2)Declare a bean definition in applicationContext-security.xml. The startup is OK (no errors) but the UserService is not autowired.
This is my applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/adminDB"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="/WEB-INF/mybatis-config.xml" />
</bean>
<bean id="usersMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="es.institution.dept.dao.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<bean id="rolesMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="es.institution.dept.dao.RoleMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<bean id="groupMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="es.institution.dept.dao.GroupMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<bean id="policyMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="es.institution.dept.dao.PolicyMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<!-- Json converter bean -->
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
<bean id="jacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper"></bean>
</beans>
This is my app-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd">
<!-- Enabling Spring beans auto-discovery -->
<context:component-scan base-package="es.institution.dept" />
<!-- Enabling Spring MVC configuration through annotations -->
<mvc:annotation-driven />
<!-- Enabling Spring Async tasks through annotations -->
<task:annotation-driven />
<mvc:view-controller path="/" view-name="login" />
<!-- Load resources -->
<mvc:resources mapping="/resources/**" location="/resources/"/>
<!-- Bean definitions i18n -->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="en" />
</bean>
<!-- Intercepts the change of the locale: example.html?ln=en -->
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="ln" />
</bean>
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" >
<property name="interceptors">
<list>
<ref bean="localeChangeInterceptor" />
</list>
</property>
</bean>
<!-- Register the messages.properties -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="WEB-INF/classes/locale/messages" />
</bean>
<!-- Defining which view resolver to use -->
<bean class= "org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
Note that UserService is working fine in other places like controllers. It seems to be a problem with the UserDetailsService itself.
If you need more info do not hesitate to write to me. I hope to solve this issue. The solution will be voted and checked.
Beans declared in root application context (applicationContext.xml and applicationContext-security.xml) cannot access beans declared in servler-specific context (app-servlet.xml)
Components of Spring Security (including UserDetailsService) must be declared in root application context
So, you need to declare UserService in applicationContext.xml instead of picking it up by <context:component-scan> in app-servlet.xml.
Related
I recently moved from Hibernate to JPA. Now I notice two things in my code.
Methods in my services do not need #Transactional anymore to perform insertion to the database.
Transaction never get rolled back even if there's any exception.
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">
<context:annotation-config />
<context:component-scan base-package="com.myapp.service, com.myapp.batch,com.myapp.auth" />
<!-- Configure the data source bean -->
<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
<property name="dataSourceProperties" >
<props>
<prop key="url">jdbc:mysql://localhost:3306/app?zeroDateTimeBehavior=convertToNull</prop>
<prop key="user">user</prop>
<prop key="password">pass</prop>
</props>
</property>
<property name="dataSourceClassName"
value="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" />
</bean>
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
<constructor-arg ref="hikariConfig" />
</bean>
<!-- Create default configuration for Hibernate -->
<bean id="hibernateJpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
<!-- Configure the entity manager factory bean -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.myapp.persist" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.c3p0.timeout">100</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean class="org.springframework.jdbc.datasource.init.DataSourceInitializer"
depends-on="entityManagerFactory">
<property name="dataSource" ref="dataSource" />
<property name="databasePopulator">
<bean
class="org.springframework.jdbc.datasource.init.ResourceDatabasePopulator">
<property name="scripts" value="classpath:initial_data.sql" />
<property name="continueOnError" value="true" />
</bean>
</property>
</bean>
<jpa:repositories base-package="com.myapp.repositories"
entity-manager-factory-ref="entityManagerFactory" />
<!-- Enable annotation driven transaction management -->
<tx:annotation-driven />
<task:annotation-driven />
</beans>
NetworkService.java
#Service
public class AdminUserManagementService {
#Autowired
UserRepository userRepository;
#Autowired
UserService userService;
#Autowired
RequestRegisterHistoryRepository requestRegisterHistoryRepository;
#Autowired
#Transactional(rollbackFor=Exception.class)
public User saveUser(UserBO userBO){
RequestRegisterHistory requestRegisterHistory = new RequestRegisterHistory();
User user = new User();
// ..
requestRegisterHistoryRepository.save(requestRegisterHistory);
userRepository.save(user);
return user;
}
}
mvc-dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="sec://www.springframework.org/schema/mvc"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<context:component-scan base-package="com.myapp.controller" />
<!-- Enables the Spring MVC #Controller programming model -->
<mvc:annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/" />
<mvc:resources mapping="/resources/**" location="resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources
in the /WEB-INF/views directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
<beans:property name="order" value="1" />
</beans:bean>
<beans:bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<beans:property name="favorPathExtension" value="false" />
<beans:property name="favorParameter" value="true" />
<beans:property name="parameterName" value="mediaType" />
<beans:property name="ignoreAcceptHeader" value="true"/>
<beans:property name="useJaf" value="false"/>
<beans:property name="defaultContentType" value="application/json" />
<beans:property name="mediaTypes">
<beans:map>
<beans:entry key="json" value="application/json" />
<beans:entry key="xml" value="application/xml" />
</beans:map>
</beans:property>
</beans:bean>
<mvc:interceptors>
<beans:bean
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<beans:property name="paramName" value="lang" />
</beans:bean>
<beans:bean class="com.myapp.component.AppInterceptor" />
</mvc:interceptors>
<beans:bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter">
<beans:property name="supportedMediaTypes" value="image/jpeg" />
</beans:bean>
<beans:bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- setting maximum upload size -->
<beans:property name="maxUploadSize" value="99999999999" />
</beans:bean>
</beans:beans>
I am using Spring Version : 4.1.4 and MySQL Table : MyISAM
Stacktrace
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:248)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:214)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:122)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy37.save(Unknown Source)
at com.myapp.service.AdminUserManagementService.saveUser(AdminUserManagementService.java:460)
at com.myapp.service.AdminUserManagementService$$FastClassBySpringCGLIB$$f21244b7.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
How do I configure so I would require #Transactional annotation and any transaction get rolled back during exceptions ?
The issue was with table engine that's MyISAM. The transaction is able to rollback after I changed the engine to InnoDB.
Setting the hibernate.dialect to org.hibernate.dialect.MySQLInnoDBDialect ensure the creation of table with InnoDBin the future.
I have implemented spring security oauth for authenticating my application.From the client application (Android app) I would like to retrieve a token for a userby using Resource owner password credentials authorization type. In case where wrong credentials are given I throw
UsernameNotFoundException exception in my custom UserDetailsService, but in my client app I do not get a proper error response. I think the server returns RuntimeException and due to this a proper response is not formed. Can you suggest me what I can do in this case? How should i set Spring Security ExceptionHandler for this? This is the exception that i got in the server.
org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [MyProject] in context with path [/MyProject] threw exception [Handler processing failed; nested exception is java.lang.StackOverflowError] with root cause
java.lang.StackOverflowError
at sun.nio.cs.UTF_8.updatePositions(UTF_8.java:77)
at sun.nio.cs.UTF_8.access$200(UTF_8.java:57)
at sun.nio.cs.UTF_8$Encoder.encodeArrayLoop(UTF_8.java:636)
at sun.nio.cs.UTF_8$Encoder.encodeLoop(UTF_8.java:691)
at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:579)
at sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:271)
at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:125)
at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:135)
at java.io.OutputStreamWriter.write(OutputStreamWriter.java:220)
at java.io.Writer.write(Writer.java:157)
at com.google.gson.stream.JsonWriter.string(JsonWriter.java:534)
at com.google.gson.stream.JsonWriter.writeDeferredName(JsonWriter.java:402)
at com.google.gson.stream.JsonWriter.value(JsonWriter.java:417)
at com.google.gson.internal.bind.TypeAdapters$13.write(TypeAdapters.java:362)
at com.google.gson.internal.bind.TypeAdapters$13.write(TypeAdapters.java:346)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
.....................
Below is my codes.
spring-security.xml :
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:sec="http://www.springframework.org/schema/security" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd ">
<http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="authenticationManager"
xmlns="http://www.springframework.org/schema/security" >
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" method="POST" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http pattern="/protected/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/protected/**" method="GET" access="ROLE_APP" />
<!-- <intercept-url pattern="/resources/**" access="IS_AUTHENTICATED_FULLY" /> -->
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http pattern="/logout" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/logout" method="GET" />
<sec:logout invalidate-session="true" logout-url="/logout" success-handler-ref="logoutSuccessHandler" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<bean id="logoutSuccessHandler" class="com.example.myproject.security.LogoutImpl" >
<property name="tokenstore" ref="tokenStore"></property>
</bean>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="exceptionTranslator" ref="myExceptionTranslator"></property>
</bean>
<bean id="myExceptionTranslator"
class="org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator">
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="springsec/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler">
</bean>
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="clientDetails" class="com.example.myproject.service.ClientService"/>
<authentication-manager id="userAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="userService">
</authentication-provider>
</authentication-manager>
<bean id="userService"
class="com.example.myproject.service.UserService">
</bean>
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices">
<oauth:authorization-code />
<oauth:implicit/>
<oauth:refresh-token/>
<oauth:client-credentials />
<oauth:password authentication-manager-ref="userAuthenticationManager"/>
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter"
resource-id="springsec" token-services-ref="tokenServices" />
<!-- <bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" /> -->
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" >
<property name="authenticationKeyGenerator">
<bean class="com.example.myproject.service.UniqueAuthenticationKeyGenerator" />
</property>
</bean>
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="accessTokenValiditySeconds" value="300000"></property>
<property name="clientDetailsService" ref="clientDetails" />
<property name="tokenEnhancer"><bean class="com.example.myproject.service.CustomTokenEnhancer" /></property>
</bean>
<sec:global-method-security
pre-post-annotations="enabled" proxy-target-class="true">
<!--you could also wire in the expression handler up at the layer of the
http filters. See https://jira.springsource.org/browse/SEC-1452 -->
<sec:expression-handler ref="oauthExpressionHandler" />
</sec:global-method-security>
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
</beans>
ClientService.java :
#Component
public class ClientService implements ClientDetailsService {
#Autowired
private OauthRepository oauthRepository;
#Override
public ClientDetails loadClientByClientId(String s) throws ClientRegistrationException{
BaseClientDetails clientDetails = oauthRepository.getByClientId(s);
return clientDetails;
}
}
UserService.java :
#Component
public class UserService implements UserDetailsService {
#Autowired
private OauthRepository oauthRepository;
#Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
UserDetails user = oauthRepository.getByUsername(s);
return user;
}
}
OauthRepository.java :
#Repository
#Transactional
public class OauthRepository {
#Autowired
private SessionFactory sessionFactory;
#Autowired
private InMemoryTokenStore tokenStore;
private org.hibernate.Session getCurrentSession(){
return sessionFactory.getCurrentSession();
}
public UserDetails getByUsername(String username) {
MyUser user=new MyUser();
user.setUserName(username);
Query query=getCurrentSession().createQuery("FROM User WHERE userName=:usrName");
query.setParameter("usrName", username);
List<SiUser> getUser=query.list();
User act=getUser.get(0);
user.setPassword(act.getPassword());
user.setUserId(act.getUserId());
user.setAuthorities(getAuthorities(act.getUserId()));
return user;
}
public BaseClientDetails getByClientId(String clientId) {
System.out.println(" *** OauthRepository.getByClientId "+clientId);
Query query=getCurrentSession().createQuery("FROM OauthClientDetails WHERE clientId=:clientId");
query.setParameter("clientId", clientId);
List<OauthClientDetails> getClient=query.list();
OauthClientDetails oauthClient=getClient.get(0);
BaseClientDetails details = new BaseClientDetails();
details.setClientId(oauthClient.getClientId());
List<String> grantTypesList = Arrays.asList(oauthClient.getAuthorizedGrantTypes().split(","));
details.setAuthorizedGrantTypes(grantTypesList);
details.setClientSecret(oauthClient.getClientSecret());
return details;
}
/**
* Retrieves a collection of {#link GrantedAuthority} based on a numerical role
* #param role the numerical role
* #return a collection of {#link GrantedAuthority
*/
public Collection<GrantedAuthority> getAuthorities(Integer role) {
List<GrantedAuthority> authList = getGrantedAuthorities(getRoles(role));
return authList;
}
/**
* Converts a numerical role to an equivalent list of roles
* #param role the numerical role
* #return list of roles as as a list of {#link String}
*/
public List<String> getRoles(Integer role) {
List<String> roles = new ArrayList<String>();
Query query=getCurrentSession().createQuery("FROM UserRole WHERE userID=:userId");
query.setParameter("userId", role);
List<SiUserRole> getUser=query.list();
UserRole actRole=getUser.get(0);
roles.add(actRole.getRole());
return roles;
}
/**
* Wraps {#link String} roles to {#link SimpleGrantedAuthority} objects
* #param roles {#link String} of roles
* #return list of granted authorities
*/
public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (String role : roles) {
authorities.add(new GrantedAuthorityImpl(role));
}
return authorities;
}
}
servlet-context.xml :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<!-- #author Nagesh.Chauhan(neel4soft#gmail.com) -->
<context:annotation-config />
<context:component-scan base-package="com.example.myproject" />
<mvc:annotation-driven />
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- one of the properties available; the maximum file size in bytes -->
<property name="maxUploadSize" value="1000000000" />
</bean>
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/MyDatabase"/>
<property name="username" value="username"/>
<property name="password" value="password"/>
<property name="validationQuery" value="SELECT 1"/>
</bean>
<!-- Hibernate Session Factory -->
<bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="packagesToScan">
<array>
<value>com.example.myproject</value>
</array>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
</value>
</property>
</bean>
<!-- Hibernate Transaction Manager -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
<!-- Activates annotation based transaction management -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
I've been stumbling for the last few days on a redirect loop when integrating a CAS SSO to one of my web app. This happens just after I've logged in thanks to the CAS
I've been monitoring the requests that are being exchanged between the CAS and my web app, and they seem to be working.
I suspect that the problem might come from a bad implementation of the user rights / tokens.
Here's my file :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:sec="http://www.springframework.org/schema/security" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<bean id="userAuditService" class="net.UserAuditServiceImpl">
<property name="passwordEncoder" ref="passwordEncoder" />
<property name="seedGenerator" ref="seedGenerator" />
<property name="canResetPassword" value="${security.resetPassword.enabled}" />
</bean>
<sec:http entry-point-ref="casEntryPoint">
<sec:intercept-url pattern="/**" access="ROLE_USER"/>
<sec:custom-filter position="CAS_FILTER" ref="casFilter" />
</sec:http>
<bean id="casEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<property name="loginUrl" value="http://localhost:8080/cas/login" />
<property name="serviceProperties" ref="serviceProperties" />
</bean>
<bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
<property name="service" value="http://localhost:8088/myapp/supervision"/>
<property name="sendRenew" value="false"/>
</bean>
<bean id="casFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationSuccessHandler">
<bean
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler" />
</property>
<property name="filterProcessesUrl" value="http://localhost:8088/myapp/supervision"/>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="casAuthenticationProvider" />
</sec:authentication-manager>
<bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<property name="authenticationUserDetailsService">
<bean id="authenticationUserDetailsService" class="net.spAuthenticationUserDetailsService" >
<constructor-arg ref="userAuditService" />
</bean>
</property>
<property name="serviceProperties" ref="serviceProperties" />
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<constructor-arg index="0" value="http://localhost:8080/cas" />
</bean>
</property>
<property name="key" value="an_id_for_this_auth_provider_only"/>
</bean>
</beans>
My AuthenticationUserDetailsService class :
public class spAuthenticationUserDetailsService implements AuthenticationUserDetailsService {
private final Logger logger = LoggerFactory.getLogger(getClass());
private UserAuditService userAuditService;
public spAuthenticationUserDetailsService(final UserAuditService userAuditService) {
this.userAuditService = userAuditService;
}
#Override
public UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException {
AuditUser user = userAuditService.findByLogin(token.getName());
logger.info(">> loadUserDetails : user name : " + user.getLogin());
return new UserDetailsAdapter(user);
}
}
Any ideas what I am doing wrong ?
Thanks !
(Note: this should be just a comment but I can't comment). Could you try just cleaning your web browser cache, I've had a similar trouble in the past with this configuration and it was just a bad cache in chrome.
I implemented spring security 3.2.5 but unfortunately #PreAuthorize does not work on classes and methods. As I read from the documentations, #PreAuthorize should allow methods and classes to work if user has specified role inside the annotation but I am able to run all the methods or classes without any difference of roles. You can see security-config.xml and security.context.xml and my class where I declared #PreAuthorize annotation below. I would be glad if you can help me about this problem.
security-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<http pattern="/securityNone" security="none" />
<http use-expressions="true">
<intercept-url pattern="/**" access="isAuthenticated()" />
<http-basic />
</http>
<global-method-security pre-post-annotations="enabled" />
<authentication-manager>
<authentication-provider>
<user-service>
<user name="alperk" password="123" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
security-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans /spring-beans-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<bean id="defaultAuthEventPublisher" class="org.springframework.security.authentication.DefaultAuthenticationEventPublisher"/>
<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
<property name="providers">
<list>
<ref bean="authenticationProvider"/>
</list>
</property>
<property name="authenticationEventPublisher" ref="defaultAuthEventPublisher"/>
</bean>
<!-- Authentication service reference -->
<bean id="customUserDetailsService" class="tr.com.sistek.utak.authentication.AuthenticationUserDetailsService"/>
<!-- Authentication yapilirken MD5 password sifreleme kullaniliyor -->
<bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder"/>
<bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="customUserDetailsService"/>
<!--<property name="passwordEncoder" ref="passwordEncoder"/>-->
</bean>
<bean id="authenticationSuccessHandler" class="tr.com.sistek.utak.authentication.CustomAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/faces/private/MainMenu.jsf"/>
</bean>
<bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
<property name="exceptionMappings">
<props>
<prop key="org.springframework.security.authentication.BadCredentialsException">/login-failure.jsf?err=HATALI_PWD</prop>
<prop key="org.springframework.security.authentication.CredentialsExpiredException">/change-password.jsf</prop>
<prop key="org.springframework.security.authentication.LockedException">/login-failure.jsf?err=HESAP_KILITLI</prop>
<prop key="org.springframework.security.authentication.DisabledException">/login-failure.jsf?err=HESAP_PASIF</prop>
</props>
</property>
</bean>
<bean id="accessDeniedHandler" class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage" value="/error401.jsf"/>
</bean>
<!-- Login Esnasinda Girilen Bilgileri Kontrol Etmek Icin Kullanilmistir -->
<bean id="customPreAuthenticationLoginHandler" class="tr.com.sistek.utak.authentication.CustomPreAuthenticationLoginHandler">
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationSuccessHandler" ref="authenticationSuccessHandler" />
<property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
<property name="filterProcessesUrl" value="/j_security_check" />
<property name="sessionAuthenticationStrategy" ref="sas" />
<property name="postOnly" value="false" />
</bean>
<sec:http pattern="/assets/**" security="none"/>
<sec:http pattern="/images/**" security="none"/>
<sec:http pattern="/resources/**" security="none"/>
<sec:http pattern="/themes/**" security="none"/>
<sec:http pattern="/javax.faces.resource/**" security="none"/>
<sec:global-method-security
pre-post-annotations="enabled"
mode="aspectj"
proxy-target-class="true">
</sec:global-method-security>
<sec:http auto-config="true" use-expressions="true"
authentication-manager-ref="authenticationManager">
<sec:intercept-url pattern="/dashboard/**" access="isAuthenticated()"/>
<sec:custom-filter before="FORM_LOGIN_FILTER" ref="customPreAuthenticationLoginHandler"/>
<sec:form-login login-page="/login.jsf"
authentication-failure-handler-ref = "authenticationFailureHandler"
default-target-url="/faces/private/MainMenu.jsf"/>
<sec:access-denied-handler ref = "accessDeniedHandler"/>
<sec:logout invalidate-session="true"
logout-success-url="/login.jsf"
logout-url="/logout"/>
<sec:session-management invalid-session-url="/login.jsf" session-authentication-strategy-ref="sas"/>
<sec:custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
</sec:http>
<bean id="jsfRedirectStrategy" class="tr.com.sistek.utak.jsf.filter.JsfRedirectStrategy"/>
<bean id="httpSessionSecurityContextRepository" class="org.springframework.security.web.context.HttpSessionSecurityContextRepository"/>
<!-- Authentication logout handler -->
<bean id="customAuthenticationLogoutHandler" class="tr.com.sistek.utak.authentication.CustomAuthenticationLogoutHandler"/>
<!-- ******************************************************************* -->
<!-- Concurrent Session Management Configuration-->
<!-- ******************************************************************* -->
<bean id="concurrencyFilter"
class="org.springframework.security.web.session.ConcurrentSessionFilter">
<property name="sessionRegistry" ref="sessionRegistry" />
<property name="expiredUrl" value="/session-expired.jsf" />
<!-- this permits redirection to session timeout page from javascript/ajax or http -->
<property name="redirectStrategy" ref="jsfRedirectStrategy" />
</bean>
<bean id="sas" class= "org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
<constructor-arg name="sessionRegistry" ref="sessionRegistry" />
<property name="maximumSessions" value="1" />
<!-- <property name="alwaysCreateSession" value="true" />
<property name="exceptionIfMaximumExceeded" value="true" />-->
</bean>
<bean id="sessionRegistry"
class="org.springframework.security.core.session.SessionRegistryImpl" />
Bean :
#ManagedBean
#ViewScoped
#PreAuthorize("hasRole('ROLE_ADMIN')")
public class OrderDetView implements Serializable {
......
This is only my first thought:
Your annotations #ManagedBean and #ViewScoped indicate that you use a JSF Framework and maybe your OrderDetView bean ins just a JSF bean but not a Spring bean. But #PreAuthorize works only for Spring beans.
I get the following error when trying to set up a Spring project with Velocity.
PageNotFound - No mapping found for HTTP request with URI [/SpringMVCVelocity/Enquiries/viewAllEnquiries] in DispatcherServlet with name 'mvc-dispatcher'
I have set up the spring context.xml as-
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd">
<context:component-scan base-package="ecommerce.dao" />
<bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<property name="resourceLoaderPath" value="/WEB-INF/view/"/>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
<property name="cache" value="false"/>
<property name="prefix" value=""/>
<property name="suffix" value=".vm"/>
<property name="order" value="-1"/>
<property name="exposeSpringMacroHelpers" value="true"></property>
</bean>
<mvc:annotation-driven/>
<!-- Forwards requests to the "/" resource to the "welcome" view -->
<mvc:view-controller path="/" view-name="welcome"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="ecommerce"/>
</bean>
<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<!-- Configures Handler Interceptors -->
<mvc:interceptors>
<!-- Changes the locale when a 'locale' request parameter is sent; e.g. /?locale=de -->
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
</mvc:interceptors>
<!-- Saves a locale change using a cookie -->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver" />
<!-- Application Message Bundle -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="/WEB-INF/messages/messages" />
<property name="cacheSeconds" value="0" />
</bean>
<!--
FLOW HANDLING
-->
<!-- Enables FlowHandler URL mapping -->
<bean id="flowController" class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
<property name="flowExecutor" ref="flowExecutor" />
</bean>
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry"/>
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
<property name="flowRegistry" ref="flowRegistry" />
<property name="order" value="-1" />
</bean>
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
<webflow:flow-location path="/WEB-INF/view/flows/flow.xml"/>
</webflow:flow-registry>
<webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="mvcViewFactoryCreator" />
<bean id="mvcViewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
<property name="viewResolvers" ref="viewResolver" />
</bean>
<!--
Bean Injections
-->
<bean id="carModelDao" class="ecommerce.dao.CarModelDao"/>
<bean id="carController" class="ecommerce.controller.CarController">
<property name="carModelDao" ref="carModelDao"/>
</bean>
<bean id="veloController" class="ecommerce.controller.VelocityController">
<property name="carModelDao" ref="carModelDao"/>
</bean>
</beans>
My controller is:
#Controller
#RequestMapping("/Enquiries")
#SessionAttributes({"enqList", "search"})
public class EnquiryController {
private static final Logger logger = Logger.getLogger(EnquiryController.class);
private PagedListHolder<Enquiry> enqList = null;
private int pageSize = 10;
#Autowired
private EnquiryDao enquiryDao;
#RequestMapping("/viewAllEnquiries")
public String getAllEnquiries(#RequestParam(required=false) String page, Model model) {
if ("next".equals(page) && enqList != null) {
enqList.nextPage();
} else if ("previous".equals(page) && enqList != null) {
enqList.previousPage();
} else {
// well there is no page parameter, so it must be a new request
enqList = new PagedListHolder<Enquiry>(enquiryDao.getAllEnquiries());
enqList.setPageSize(pageSize);
}
model.addAttribute("search", new Search());
model.addAttribute("enqList", enqList);
return "viewAllEnquiries";
}
This controller is not even called. It does however successfully manage to resolve the welcome view with:
<mvc:view-controller path="/" view-name="welcome"/>
Problem solved,
I wasn't scanning the controller (context:component-scan) and had not wired the bean either in the Spring context.
So to fix it, I added it via spring injection:
<bean id="enquiryDao" class="ecommerce.dao.EnquiryDao"/>
<bean id="enquiryController" class="ecommerce.controller.EnquiryController">
<property name="enquiryDao" ref="enquiryDao"/>
</bean>