Comportamiento extraño de SpringSecurity - Resuelto

Que tal, les explico el contexto de mi problema y luego mi configuración.

Tengo dos proyectos, uno es un proyecto Web con Maven3 / Spring3 / SpringSecurity3 / Hibernate3 / Mysql / Base de datos ApWeb, lo llamaré AplicacionWeb; el otro es un componente de seguridad con las mismas tecnologías, lo llamaré ComponenteSeguridad.

Hice esto porque necesito tener un componente externo que obtenga los usuarios de la base de datos (BD) de Recursos Humanos (RH) y que pueda ser usado por cualquier otra aplicación que requiera tener esta misma característica.

La configuración de la seguridad está en un archivo security.xml que está en AplicacionWeb, esto para tener un comportamiento particular de la seguridad para esta aplicación.

Para entrar a la AplicacionWeb, lo que hago primero es buscar usuarios en la BD de RH, esto con la ayuda del ComponenteSeguridad y posteriormente los usuarios locales en la BD de ApWeb.

Una vez dentro, puedo gestionar los usuarios de la BD de ApWeb, además, puedo tener en ApWeb, usuarios de RH, pero solo las credenciales, sin los detalles, cuando necesito ver detalles de un usuario de RH que está en ApWeb, me traigo los detalles de RH.

Ahora, el problema que tengo es que cuando estoy en el módulo de administración de usuarios e intento obtener los detalles de un usuario de RH que tmbn está en ApWeb, me saca de la aplicación y me regresa al login. Después de depurar un poco encontré que únicamente sucede cuando intento obtener datos de usuarios de RH, si obtengo datos de usuarios locales funciona muy bien. La porción de código que hace esto está en web.app.webapp.controller.UserFormController:

         private security.component.service.UsuarioRHManager rhUsuarioRHManager = null;

        @Autowired
        public void setRhUsuarioRHManager(security.component.service.UsuarioRHManager rhUsuarioRHManager) {
                this.rhUsuarioRHManager = rhUsuarioRHManager;
        }

        @ModelAttribute
        @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST})
        protected Usuario showForm(HttpServletRequest request, HttpServletResponse response) throws Exception {
                /*
                   ....
                   Mi codigo
                   ...
                */

                if(esRH) {
                        /** Linea del problema **/
                        security.component.model.UsuarioRH usuarioRH = rhUsuarioRHManager.getUserByUsername(usuario.getUsername());
                        web.app.webapp.model.UsuarioDetalle detalleRH = new UsuarioDetalle(usuarioRH);
                        usuario.setDetalle(detalleRH);
                }
                return usuario;
      }

Ahora, mis configuraciones son las siguientes:

ComponenteSeguridad

/moduloseguridad/src/main/resources/applicationContext-rh_dao.xml

    <context:annotation-config/>

        <bean id="rhDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost/recursos_humanos?createDatabaseIfNotExist=true&amp;amp;useUnicode=true&amp;amp;characterEncoding=utf-8&amp;amp;autoReconnect=true"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
        <property name="maxActive" value="100"/>
        <property name="maxWait" value="1000"/>
        <property name="poolPreparedStatements" value="true"/>
        <property name="defaultAutoCommit" value="true"/>
    </bean>
   
    <bean id="rhSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="rhDataSource"/>
        <property name="configLocation" value="classpath:rh_hibernate.cfg.xml"/>
        <property name="hibernateProperties">
            <value>
                hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
                hibernate.query.substitutions=true 'Y', false 'N'
                hibernate.cache.use_second_level_cache=true
                hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
            </value>
           
           
        </property>
    </bean>
   
    <bean id="rhTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="rhSessionFactory"/>
    </bean>

/moduloseguridad/src/main/resources/applicationContext-rh_service.xml

    <tx:annotation-driven/>
   
    <aop:aspectj-autoproxy/>
   
    <context:annotation-config/>
       
    <bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder"/>

/moduloseguridad/src/main/resources/rh_hibernate.cfg.xml

<session-factory>
        <mapping class="security.component.model.UsuarioRH"/>
        <!-- No manejo roles en RH -->
</session-factory>

AplicacionWeb

/webapplication/src/main/resources/applicationContext-dao.xml

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
   
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:hibernate.cfg.xml"/>
        <property name="hibernateProperties">
            <value>
                hibernate.dialect=${hibernate.dialect}
                hibernate.query.substitutions=true 'Y', false 'N'
                hibernate.cache.use_second_level_cache=true
                hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
                hibernate.show_sql=true
                hibernate.format_sql=true
            </value>
           
           
        </property>
    </bean>

   
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
   
   
    <context:component-scan base-package="security.component.dao, web.app.dao"/>

/webapplication/src/main/resources/applicationContext-resources.xml

    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="ignoreUnresolvablePlaceholders" value="true"/>
        <property name="locations">
            <list>
                <value>classpath:jdbc.properties</value>
                <value>classpath:mail.properties</value>
            </list>
        </property>
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="maxActive" value="100"/>
        <property name="maxWait" value="1000"/>
        <property name="poolPreparedStatements" value="true"/>
        <property name="defaultAutoCommit" value="true"/>
    </bean>

/webapplication/src/main/resources/applicationContext-service.xml

    <aop:config>
        <aop:advisor id="userManagerTx" advice-ref="userManagerTxAdvice" pointcut="execution(* *..service.UserManager.*(..))" order="0"/>        
        <aop:advisor id="userManagerSecurity" advice-ref="userSecurityAdvice" pointcut="execution(* *..service.UserManager.saveUser(..))" order="1"/>
        <aop:advisor id="managerTx" advice-ref="txAdvice" pointcut="execution(* *..service.*Manager.*(..))" order="2"/>
    </aop:config>
   
    <tx:advice id="txAdvice">
        <tx:attributes>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

    <tx:advice id="userManagerTxAdvice">
        <tx:attributes>
            <tx:method name="save*" rollback-for="UserExistsException"/>
        </tx:attributes>
    </tx:advice>
   
    <bean id="userSecurityAdvice" class="web.app.service.UserSecurityAdvice"/>
   
   
    <context:component-scan base-package="security.component.service, web.app.service"/>
   
    <bean id="mailEngine" ... />
    <bean id="mailSender" ... />
    <bean id="velocityEngine" ... />
    <bean id="mailMessage" ... />
    <bean id="usuarioDetalleManager" ... />

/webapplication/src/main/resources/hibernate.cfg.xml

<session-factory>
    <mapping class="web.app.model.Usuario"/>
    <mapping class="web.app.model.UsuarioDetalle"/>
    <mapping class="web.app.model.Role"/>
    <mapping class="web.app.model.Bitacora"/>
</session-factory>

¿Qué creen que pueda ser?
¿Qué me recomiendan hacer?
¿Si necesitan alguna otra información?
Espero sus comentarios.
Gracias.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

La solución a mi problema

Creo que debí haber pegado también mi código.
Pasa que el método que estaba usando

    /** Linea del problema **/
    security.component.model.UsuarioRH usuarioRH = rhUsuarioRHManager.getUserByUsername(usuario.getUsername());
   

invoca a un método de la capa DAO, el

    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {...}
   

Pues bien, este es el método usado por defecto por SpringSecurity para buscar las credenciales del usuario para la autenticación. En mi caso, como los detalles del usuario que estaba intentando obtener no existen en la BD de RH, Hibernate me mandaba un NPE al intentar ejecutar métodos del objeto detalle; pero la excepción no era lanzada, en cambio, Spring AOP capturaba el UsernameNotFoundException de Spring Security, por lo tanto hacía como wrapper de la excepción. Pero como tenía comentado los logs de Spring Security en el Log4j no me mostraba nada en la consola.

Lo que aprendí es. Hay que tener cuidado con el método loadUserByUsername y con la excepción UsernameNotFoundException de SS. Mi solución fue simplemente implementar un nuevo método que realiza la misma acción de ese método, y entonces si me lanza el NPE esperado.

Saludos.