Announcement Announcement Module
Collapse
No announcement yet.
EntityManager null when implementing UserDetailsService Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • EntityManager null when implementing UserDetailsService

    Hi,

    i am using spring security 3.1.1 with hibernate-entitymanager 3.6.0.
    What i want is my own UserDetailsService within my application so i can use my own user class.
    For this i implemented the UserDetailsService interface which looks like this:

    Code:
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    @Service("userRepositoryImpl")
    public class UserRepositoryImpl implements UserDetailsService {
    
            @PersistenceContext
            private EntityManager entityManager;
    
            @Override
            @Transactional(readOnly = true)
            public User loadUserByUsername(String username)
                            throws UsernameNotFoundException {
                    User user = entityManager.find(User.class, username);
                    if (user == null)
                            throw new UsernameNotFoundException("Username not found: "
                                            + username);
                    return user;
            }
    
    }
    But everytime i try to login using the default spring security login form the entityManager is null.
    The same happens if i try to autowire my userDao, it is null in the context of the UserDetailsService.

    However, using the entityManager in my generic dao to retrieve and save data to database it works fine:

    Code:
    @Transactional
    public abstract class DaoImpl<T> implements Dao<T> {
    
        private Class<T> type;
    
        @PersistenceContext
        protected EntityManager em;
    
        public DaoImpl() {
                Type t = getClass().getGenericSuperclass();
                ParameterizedType pt = (ParameterizedType) t;
                type = (Class) pt.getActualTypeArguments()[0];
        }
    ...
    }
    This is my security.xml:

    Code:
    <http use-expressions="true" auto-config="true">
        <intercept-url pattern="/task/" access="permitAll" />
        <intercept-url pattern="/task/**" access="isAuthenticated()" />
    
        <!-- <intercept-url pattern="/**" access="denyAll" /> -->
        <form-login />
    </http>
    
    <beans:bean id="userRepositoryImpl" class="de.sveri.jeiwomisa.model.UserRepositoryImpl" autowire="byType">
    </beans:bean>        
    <beans:bean id="passwordEncoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder">
    </beans:bean>
    <authentication-manager>
        <authentication-provider user-service-ref="userRepositoryImpl">
            <password-encoder ref="passwordEncoder" />
        </authentication-provider>
    </authentication-manager>
    and this is my db.xml including the entityManagerFactory definition:

    Code:
    <bean id="placeholderConfig"
    		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    		<property name="location" value="classpath:db.properties" />
    	</bean>
    
    	<bean id="entityManagerFactory"
    		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    		<property name="jpaVendorAdapter">
    			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    				<property name="showSql" value="true" />
    				<property name="generateDdl" value="true" />
    				<property name="databasePlatform" value="${db.dialect}" />
    			</bean>
    		</property>		
    	</bean>
    
    	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    		destroy-method="close">
    		<property name="driverClassName" value="${db.driver}" />
    		<property name="url" value="${db.url}" />
    		<property name="username" value="${db.username}" />
    		<property name="password" value="${db.password}" />
    	</bean>
    
    	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" />
    </beans>
    As i am fairly new to the spring framework i think that i am missing something fundamentally here, maybe someone can pinpoint me into the right direction?

    Regards,
    Sven

  • #2
    You have to enable the @Transactional Annotation processing:

    <tx:annotation-driven transaction-manager="transactionManager"/>

    Comment


    • #3
      Originally posted by spgmx View Post
      You have to enable the @Transactional Annotation processing:

      <tx:annotation-driven transaction-manager="transactionManager"/>
      Thank you for that hint.
      If i add that line to db.xml i am able to use my daos like UserDao in the UserRepositoryImpl class now.
      But it still cannot access the entityManager there as it still is null.

      Do i miss another configuration?

      Thanks,
      Sven

      Comment


      • #4
        Annotate UserRepositoryImpl with @Transactional.

        Comment


        • #5
          Originally posted by spgmx View Post
          Annotate UserRepositoryImpl with @Transactional.
          I did, but it still does not work -.-

          Comment


          • #6
            My guess is that your generic dao is being created in the Spring MVC configuration and it has the PersistenceAnnotationBeanPostProcessor registered as mentioned in the documentation. Remember that the DispatcherServlet configuration does not impact the Spring Security configuration. Moreover, BeanPostProcessor of the parent context will not impact that of the child but its beans will be visible to the child context. Try adding the following to your Spring Security (I also included the namespace declaration):

            Code:
            <?xml version="1.0" encoding="UTF-8"?>
            <b:beans xmlns:b="http://www.springframework.org/schema/beans"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns="http://www.springframework.org/schema/security"
              xmlns:context="http://www.springframework.org/schema/context"
              xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schem...curity-3.1.xsd
                http://www.springframework.org/schema/beans http://www.springframework.org/schem...-beans-3.1.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
              ...
            
              <context:annotation-config/>
            
            </b:beans>
            You may need to check to ensure that your beans are only being created once. For example if you are using classpath scanning ensure that your beans are only created once in the DispatcherServlet's context or in the parent context not both. To do this you would typically use something like the following. Check out the spring reference for further details.

            Code:
              <context:component-scan base-package="org.springsource.forum">
                <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
              </context:component-scan>

            Comment


            • #7
              Thank you very much, the first hint regarding the namespace und the annotation-config did the trick :-)

              Best Regards,
              Sven

              Comment

              Working...
              X