spring 3.1 with hibernate 4 with spring security 3.1: How do I ensure transactions are adviced before spring security.
-
14-11-2019 - |
Question
In my web.xml
openSessionInView org.springframework.orm.hibernate4.support.OpenSessionInViewFilter
<init-param>
<param-name>singleSession</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<!-- open session in view mapping -->
<filter-mapping>
<filter-name>openSessionInView</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
In my applicationContext-main.xml i have
<aop:config>
<aop:pointcut id="serviceMethods"
expression="execution(* com.utility.*.*(..))" />
<aop:advisor advice-ref="ownership.methodSecurityInterceptor"
pointcut-ref="com.serviceMethods" order="2" />
</aop:config>
In my applicationContext-spring-security.xml i have the following bean define
my mcl service.
public class CustomMethodDefinitionServiceImpl
implements MethodSecurityMetadataSource {
private final MclDao mclDao;
@Autowired(required = true)
public CustomMethodDefinitionServiceImpl(final MclDao mclDao) {
super();
this.mclDao = mclDao;
}
@Override
@Transactional(readOnly=true, propagation=Propagation.REQUIRED)
public Collection<ConfigAttribute> getAllConfigAttributes() {
return this.getMetaDataSource().getAllConfigAttributes();
}
@Override
public Collection<ConfigAttribute> getAttributes(final Method method, final Class<?> targetClass) {
return ((MapBasedMethodSecurityMetadataSource) this.getMetaDataSource()).getAttributes(method, targetClass);
}
@Override
public Collection<ConfigAttribute> getAttributes(final Object obj)
throws IllegalArgumentException {
return this.getMetaDataSource().getAttributes(obj);
}
@Override
public boolean supports(final Class<?> clazz) {
return clazz.isInterface();
}
public SecurityMetadataSource getMetaDataSource() {
final List<MethodControlList> methodConrolLists = this.mclDao.getAllMethodControlList();
final List<ConfigAttribute> configList = new LinkedList<ConfigAttribute>();
final Map<String, List<ConfigAttribute>> methodMap = new LinkedHashMap<String, List<ConfigAttribute>>();
for (final MethodControlList mcl : methodConrolLists) {
final StringBuilder serviceNameBuilder = new StringBuilder();
final ClassMethod classMethod = mcl.getClassMethod();
serviceNameBuilder.append(classMethod.getClassName());
serviceNameBuilder.append(".");
serviceNameBuilder.append(classMethod.getMethodName());
final List<Role> roles = this.mclDao.getAllRoleThatCanAccessClassAndMethod(classMethod.getClassName(), classMethod.getMethodName());
for (final Role role : roles) {
configList.add(new SecurityConfig(role.getAuthority()));
}
methodMap.put(serviceNameBuilder.toString(), configList);
}
return new MapBasedMethodSecurityMetadataSource(methodMap);
}
}
my MclDao
public List<Role> getRolesThatCanAccessClassAndMethod(final String className, final String methodName) {
this.sessionFactory.getCurrentSession()
.getNamedQuery("getRolesThatCanAccessMethod")
.setString("className", className)
.setString("methodName", methodName)
.list();
}
When I start the application i get this error.
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'methodSecurityInterceptor' defined in class path resource [applicationContext-spring-security.xml]: Invocation of init method failed; nested exception is org.springframework.orm.hibernate4.HibernateSystemException: No Session found for current thread; nested exception is org.hibernate.HibernateException: No Session found for current thread
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1455)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor.getAdvice(AbstractBeanFactoryPointcutAdvisor.java:85)
at org.springframework.aop.aspectj.AspectJProxyUtils.isAspectJAdvice(AspectJProxyUtils.java:67)
at org.springframework.aop.aspectj.AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(AspectJProxyUtils.java:49)
at org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator.extendAdvisors(AspectJAwareAdvisorAutoProxyCreator.java:101)
at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:88)
at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:68)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:359)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1461)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
... 22 more
Caused by: org.springframework.orm.hibernate4.HibernateSystemException: No Session found for current thread; nested exception is org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:199)
at org.springframework.orm.hibernate4.HibernateExceptionTranslator.convertHibernateAccessException(HibernateExceptionTranslator.java:50)
at org.springframework.orm.hibernate4.HibernateExceptionTranslator.translateExceptionIfPossible(HibernateExceptionTranslator.java:37)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy73.getAllMethodControlList(Unknown Source)
at com.util.security.service.impl.CustomMethodDefinitionServiceImpl.getMetaDataSource(CustomMethodDefinitionServiceImpl.java:63)
at com.util.security.service.impl.CustomMethodDefinitionServiceImpl.getAllConfigAttributes(CustomMethodDefinitionServiceImpl.java:43)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.afterPropertiesSet(AbstractSecurityInterceptor.java:137)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
... 39 more
Caused by: org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:883)
at com.util.security.dao.impl.MclDaoHibernateImpl.getAllMethodControlList(MclDaoHibernateImpl.java:88)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
... 47 more
I am guessing it is because validating the config attribute on startup before web.xml gets invoke, than how would I ensure that their is a session during startup on application?
** try it with advice below of adding @Transactional, still having the same problem. ** ** I use order = 1 for annotation driven and aop 2 so it would have transaction first, but it doesn't seem to work.
Solution
When openSessionInView
filter is not active, getCurrentSession()
should be called inside an existing transaction.
So, to ensure creation of transaction you need to make your service method @Transactional
as well (or change propagation of your DAO method to REQUIRED
).