I am trying to implement the following: clear some details from DB on SpringSecurity logout handler. The main problem that after trying to get user details from DB I get this error. The rest of code and even the same method work fine in other cases.
public class CurrentUserLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
/**
*
*/
@Autowired
private RequestsService requestsService;
/**
*
*/
@Autowired
private OffersService offersService;
/**
*
*/
@Autowired
private UsersService usersService;
/**
*
*/
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
if (authentication != null) {
UserDetailsExtended details = (UserDetailsExtended) authentication.getPrincipal();
User user = usersService.get(details.getId()); // fails here
requestsService.unlockAllByBackoffice(user);
offersService.unlockAllByBackoffice(user);
}
setDefaultTargetUrl("/");
super.onLogoutSuccess(request, response, authentication);
}
}
Config:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.ejl.butler.object.data" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
<prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
DAO:
public User get(final Long id) {
Session session = SessionFactoryUtils.getSession(sessionFactory, false);
return (User) session.get(User.class, id);
}
Spring security config:
<logout invalidate-session="true" logout-url="/logout" success-handler-ref="logoutSuccessHandler"/>
Exception:
No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
at org.springframework.orm.hibernate3.SessionFactoryUtils.doGetSession(SessionFactoryUtils.java:356)
at org.springframework.orm.hibernate3.SessionFactoryUtils.getSession(SessionFactoryUtils.java:202)
@Transactional
resolves the problem but I can't understand why? I mean it fails only in this handler in all other calls this method works fine without this annotation!
Thank you in advance!
UPD:
My temporary solution is to add @Transactional
to whole onLogoutSuccess
method.. It works)
If you have defined a
TransactionManager
in your spring context you have to specify@Transactional
somewhere in the stack. Otherwise you will get the exception you encountered because you are trying to run a query outside of a transaction.There are workarounds to this such specifying
current_session_context_class
in your hibernate configuration tothread
orbut it's not production safe..The possible values for
current_session_context_class
arejta
,thread
andmanaged
. Further to that,jta
andthread
are supported by hibernate out of box.thread
context is used in most stand alone hibernate apps or those based on light weight frameworks like Spring andjta
is used in Java EE environments.Also try
sessionFactory.getCurrentSession()
instead ofSessionFactoryUtils.getSession()
.