Bonjour,

Voici ma situation:
Nous avons, dans ma société, une application qui expose des webServices REST que nous gérons avec CXF et Spring 3.0.5.
Dans cette application, nous gérons la sécurité avec Spring via un custom AuthenticationProvider. Pour cela nous étendons la classe AbstractUserDetailsAuthenticationProvider qui implémente elle-même l'interface AuthenticationProvider.
Pour la persistence, nous utilisons le couple Hibernate et Envers 3.5.0

Mon soucis est que mon custom AuthenticationProvider (SecurityProvider.java) n'est pas transactionnel même si on lui indique de l'être via l'annotation @Transactional.
La conséquence directe est que si nous voulons faire un save via un dao dans ce SecurityProvider, Envers nous crache une NulPointerException parce qu'il ne trouve pas de transaction.

Voici un exemple de ma config Web
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
 
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5" metadata-complete="true">
 
    <distributable/>
 
    <!--INFO metadata-complete : This attribute defines whether the web descriptor is complete, or whether the class files of the web application should be examined for annotations that specify deployment information. If the attribute is set to true, the deployment tool must ignore any servlet annotations present in the class files and use only the configuration details mentioned in the descriptor. Otherwise, if the value is not specified or set to false, the container must scan all class files of the application for annotations. This provides a way to enable or disable scanning of the annotation and its processing during the startup of the application.-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
 
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:biz/trucmuche/pie2/backoffice/spring-config.xml
            /WEB-INF/spring-security.xml
        </param-value>
    </context-param>
 
    <context-param>
        <param-name>webAppRootKey</param-name>
        <param-value>pie2-backoffice.root</param-value>
    </context-param>
 
    <filter>
        <filter-name>openSessionInView</filter-name>
        <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
        <init-param>
            <param-name>sessionFactoryBeanName</param-name>
            <param-value>el2SessionFactory</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>openSessionInView</filter-name>
        <servlet-name>ws</servlet-name>
    </filter-mapping>
 
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>biz.trucmuche.pie2.el2.backoffice.security.CustomRevisionEnversFilter</filter-class>
    </filter>
 
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
 
    <servlet>
        <servlet-name>ws</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
 
    <servlet-mapping>
        <servlet-name>ws</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>
voici une partie de ma config Spring
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jaxrs="http://cxf.apache.org/jaxrs"
       xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">
 
    <import resource="classpath:META-INF/cxf/cxf.xml"/>
    <!--<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>-->
    <!--<import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml"/>-->
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
 
    <import resource="classpath:biz/trucmuche/pie2/persist/spring-config.xml"/>
    <import resource="classpath:biz/trucmuche/pie2/business/spring-config.xml"/>
    <import resource="classpath:biz/trucmuche/pie2/legacy/spring-config.xml"/>
 
    <context:annotation-config/>
 
    <context:component-scan base-package="biz.trucmuche.pie2.el2.backoffice.legacy.dao"/>
    <context:component-scan base-package="biz.trucmuche.pie2"/>
 
....
 
<tx:annotation-driven transaction-manager="transactionManager"/>

voici mon spring-security.xml
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:s="http://www.springframework.org/schema/security"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.3.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
 
    <context:annotation-config/>
 
    <context:component-scan base-package="biz.trucmuche.pie2"/>
    <!--<tx:annotation-driven transaction-manager="transactionManager"/>-->
 
    <s:global-method-security jsr250-annotations="enabled" secured-annotations="enabled" pre-post-annotations="enabled">
        <s:expression-handler ref="expressionHandler"/>
    </s:global-method-security>
 
    <bean id="permissionEvaluator" class="biz.trucmuche.pie2.el2.backoffice.security.PermissionEvaluator">
        <constructor-arg index="0">
            <map key-type="java.lang.String" value-type="biz.trucmuche.pie2.el2.backoffice.security.permission.Permission">
                <entry key="customer" value-ref="customerPermission"/>
                <entry key="authentication" value-ref="authenticationPermission"/>
                <entry key="calculationResult" value-ref="billPermission"/>
                <entry key="meter" value-ref="meterPermission"/>
                <entry key="ean" value-ref="eanPermission"/>
                <entry key="location" value-ref="locationPermission"/>
                <entry key="webUser" value-ref="webUserPermission"/>
                <entry key="mailModification" value-ref="mailModificationPermission"/>
                <entry key="coreService" value-ref="coreServicePermission"/>
            </map>
        </constructor-arg>
    </bean>
 
    <!--<bean id="securityExceptionMapper" class="biz.trucmuche.pie2.el2.backoffice.security.SecurityExceptionMapper"/>-->
 
    <bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
        <property name="permissionEvaluator" ref="permissionEvaluator"/>
    </bean>
 
    <s:http use-expressions="true">
        <s:http-basic/>
    </s:http>
 
    <s:authentication-manager>
        <s:authentication-provider ref="userService"/>
    </s:authentication-manager>
 
    <bean id="usersProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="locations">
            <list>
                <value>classpath:biz/trucmuche/pie2/backoffice/security/users.properties</value>
            </list>
        </property>
    </bean>
 
    <bean id="rolesProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="locations">
            <list>
                <value>classpath:biz/trucmuche/pie2/backoffice/security/roles.properties</value>
            </list>
        </property>
    </bean>
 
</beans>

et pour finir voici ma classe SecurityProvider (en partie):
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
 
package biz.trucmuche.pie2.el2.backoffice.security;
 
@Transactional(value = "transactionManager")
@Service("userService")
public class SecurityProvider extends AbstractUserDetailsAuthenticationProvider {
 
    private static final String APPLICATION_NAME = "pie2-backoffice";
 
    @Autowired
    private MyUtils myUtils;
 
    @Autowired
    @Qualifier("usersProperties")
    private Properties userProperties;
 
    @Autowired
    @Qualifier("rolesProperties")
    private Properties roleProperties;
 
    @Autowired
    private AppSettingDao appSettingDao;
Voici aussi la stacktrace que j'ai lorsque j'appelle un save ou saveorUpdate dans un dao autowiré dans mon SecurityProvider.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
 
13:45:55,811 ERROR [org.hibernate.event.def.AbstractFlushingEventListener] (http--0%3A0%3A0%3A0%3A0%3A0%3A0%3A0-8080-2) Could not synchronize database state with session: org.hibernate.TransactionException: could not register synchronization
at org.hibernate.transaction.JTATransaction.registerSynchronization(JTATransaction.java:316) [hibernate-core-3.5.0-Final.jar:3.5.0-Final]
at org.hibernate.envers.synchronization.AuditSyncManager.get(AuditSyncManager.java:56) [hibernate-envers-3.5.0-Final.jar:3.5.0-Final]
at org.hibernate.envers.event.AuditEventListener.onPostInsert(AuditEventListener.java:146) [hibernate-envers-3.5.0-Final.jar:3.5.0-Final]
at org.hibernate.action.EntityInsertAction.postInsert(EntityInsertAction.java:148) [hibernate-core-3.5.0-Final.jar:3.5.0-Final]
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:127) [hibernate-core-3.5.0-Final.jar:3.5.0-Final]
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:268) [hibernate-core-3.5.0-Final.jar:3.5.0-Final]
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:260) [hibernate-core-3.5.0-Final.jar:3.5.0-Final]
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:179) [hibernate-core-3.5.0-Final.jar:3.5.0-Final]
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) [hibernate-core-3.5.0-Final.jar:3.5.0-Final]
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51) [hibernate-core-3.5.0-Final.jar:3.5.0-Final]
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206) [hibernate-core-3.5.0-Final.jar:3.5.0-Final]
at org.springframework.orm.hibernate3.HibernateAccessor.flushIfNecessary(HibernateAccessor.java:390) [spring-orm-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:407) [spring-orm-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374) [spring-orm-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:737) [spring-orm-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at biz.trucmuche.pie2.el2.persist.dao.hibernate.GenericDaoHibernate.save(GenericDaoHibernate.java:46) [pie2-persist-2.9.0-SNAPSHOT.jar:]
at biz.trucmuche.pie2.el2.persist.dao.hibernate.GenericDaoHibernate.save(GenericDaoHibernate.java:28) [pie2-persist-2.9.0-SNAPSHOT.jar:]
at biz.trucmuche.pie2.el2.backoffice.security.SecurityProvider.addWebConnection(SecurityProvider.java:156) [classes:]
at biz.trucmuche.pie2.el2.backoffice.security.SecurityProvider.createSuccessAuthentication(SecurityProvider.java:118) [classes:]
at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:172) [spring-security-core-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.java:130) [spring-security-core-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.security.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:48) [spring-security-core-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.java:148) [spring-security-core-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.security.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:48) [spring-security-core-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:142) [spring-security-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) [spring-security-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79) [spring-security-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) [spring-security-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:169) [spring-security-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237) [spring-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167) [spring-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at biz.trucmuche.pie2.el2.backoffice.security.CustomRevisionEnversFilter.doFilter(CustomRevisionEnversFilter.java:20) [classes:]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.10.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.10.Final.jar:]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.10.Final.jar:]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.10.Final.jar:]
at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:154) [jboss-as-web-7.1.0.Final.jar:7.1.0.Final]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.10.Final.jar:]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.10.Final.jar:]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.10.Final.jar:]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.10.Final.jar:]
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.10.Final.jar:]
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.10.Final.jar:]
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.10.Final.jar:]
at java.lang.Thread.run(Thread.java:680) [classes.jar:1.6.0_31]
Caused by: java.lang.NullPointerException
at org.hibernate.transaction.JTATransaction.registerSynchronization(JTATransaction.java:313) [hibernate-core-3.5.0-Final.jar:3.5.0-Final]
... 44 more
Voilà si qqn a déjà pu expérimenter ce genre de situation. Je suis preneur de toute idée.

bonne journée
Olivier