1

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)

5
  • Is your logout url intercepted by Spring MVC? Commented Sep 4, 2013 at 8:24
  • @shamimz I added security config to question.. No, I just specified the logout handler but the url itself isn't intercepted by Spring Commented Sep 4, 2013 at 8:26
  • Can you submit what error message you are getting? Commented Sep 4, 2013 at 8:28
  • @shamimz By the way.. I think if I specified logout url in config so it should be intercepted by Spring automatically Commented Sep 4, 2013 at 9:03
  • Do you by any chance use a OpenSessionInViewFilter or interceptor? Commented Sep 4, 2013 at 11:24

1 Answer 1

1

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 to thread or

<property name="current_session_context_class">org.hibernate.context.ThreadLocalSessionContext</property>

but it's not production safe..

The possible values for current_session_context_class are jta, thread and managed. Further to that, jta and thread 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 and jta is used in Java EE environments.

Also try sessionFactory.getCurrentSession() instead of SessionFactoryUtils.getSession().

Sign up to request clarification or add additional context in comments.

10 Comments

both of them aren't production safe?
I just trying to understand why the same piece of code works fine in other cases
Could you give more details on what other cases this code works okay? Also, where do you apply the @Transactional annotation in your code?
Try <tx:annotation-driven transaction-manager="transactionManager" />
When using spring NEVER mess around with the current_session_context_class property of hibernate. Unless you use JTA. Anuthing else (or setting it to thread) will break proper Spring transaction management (Spring has its own CurrentSessionContext implementation for proper integration)!. Next to that you really should use SessionFactory.getCurrentSession insteaf of the utility class you have now.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.