Bonjour à tous, je suis débutant en Spring. Je tente de créer un web service permettant d’interagir avec une base de donnée.
Pour cela je dispose de :
- MySQL
- Hibernate 3.6.6
- Spring 3.0.5.RELEASE
- Spring-WS 2.0.2.RELEASE
- Tomcat 7

J'ai configuré Spring pour utiliser JPA.

spring.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
 
<beans>
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" />
 
	<bean id="persistenceUnitManager"
		class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
		<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml" />
		<property name="dataSources">
			<map>
				<entry key="localDataSource" value-ref="dataSource" />
			</map>
		</property>
	</bean>
 
	<bean id="entityManagerFactory"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="persistenceUnitManager" ref="persistenceUnitManager" />
	</bean>
 
	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory" />
	</bean>
 
	<tx:annotation-driven transaction-manager="transactionManager" />
 
	<context:annotation-config />
	<context:component-scan base-package="fr.company.compta.business" />
 
</beans>
persistence.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
 
<persistence>
 
	<persistence-unit name="compta-business" transaction-type="RESOURCE_LOCAL">
 
		<provider>org.hibernate.ejb.HibernatePersistence</provider>
 
		...
		<class>fr.company.compta.business.data.entity.Thirdparty</class>
		...
 
		<properties>
			<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect"/>
			<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
			<property name="hibernate.connection.username" value="compta"/>
			<property name="hibernate.connection.password" value="compta"/>
			<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/compta"/>
			<property name="hibernate.hbm2ddl.auto" value="validate" />
			<property name="hibernate.show_sql" value="true" />
		</properties>
 
	</persistence-unit>
 
</persistence>
Mon point d'entrée est un web service, d'où la présence d'un web.xml

web.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
 
<web-app>
 
	<display-name>Compta Business</display-name>
 
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:/META-INF/spring.xml</param-value>
	</context-param>
 
	<servlet>
		<servlet-name>spring-ws</servlet-name>
		<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
		<init-param>
			<param-name>transformWsdlLocations</param-name>
			<param-value>true</param-value>
		</init-param>
	</servlet>
 
	<servlet-mapping>
		<servlet-name>spring-ws</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>
 
	<listener>
		<listener-class>
			 org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>
 
</web-app>
Je tente d'appeler un service pour insérer un objet en base. Pour cela le endpoint appelle une classe service gérant les transactions, cette dernière appelle une DAO, qui elle appelle une DAO générique.
Et bien sûr cette dernière utilise l'entityManager configuré.

Endpoint : appel de "createThirdpartyRequest" via SOAP UI
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
 
@Endpoint
public class BasicEndpoint {
 
	private static final String NAMESPACE_URI = "http://company.fr/compta/schemas";
	private XPath nameExpression;
 
	private ThirdpartyService thirdpartyService;
 
	@Autowired
	public BasicEndpoint(ThirdpartyService thirdpartyService)
			throws JDOMException {
		this.thirdpartyService = thirdpartyService;
 
		Namespace namespace = Namespace.getNamespace("x", NAMESPACE_URI);
 
		nameExpression = XPath.newInstance("//x:Name");
		nameExpression.addNamespace(namespace);
	}
 
	@PayloadRoot(namespace = NAMESPACE_URI, localPart = "CreateThirdpartyRequest")
	public void createThirdpartyRequest(
			@RequestPayload Element createThirdpartyRequest) throws Exception {
 
		String name = nameExpression.valueOf(createThirdpartyRequest);
 
		thirdpartyService.createThirdparty(name);
	}
}
Service
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
 
@Service("ThirdpartyService")
@Transactional
public class ThirdpartyServiceImpl implements ThirdpartyService {
 
	@Autowired
	private ThirdpartyDao thirdpartyDao;
 
	@Override
	@Transactional(readOnly = false)
	public void createThirdparty(String name) {
		Thirdparty thirdparty = new Thirdparty(name);
		thirdpartyDao.create(thirdparty);
	}
}
DAO
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
@Service("ThirdpartyDao")
public class ThirdpartyDaoImpl implements ThirdpartyDao {
 
	@Autowired
	private GenericDao dao;
 
	@Override
	public void create(Thirdparty thirdparty) {
		dao.create(thirdparty);
	}
 
	...
}
DAO générique
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
 
@Repository("GenericDao")
@Transactional(propagation=Propagation.MANDATORY)
public class GenericDaoImpl implements GenericDao {
 
	@PersistenceContext
	private EntityManager em;
 
	@Override
	@Transactional(propagation=Propagation.REQUIRED, readOnly=true)
	public <T> T create(T t) {
		em.persist(t);
		em.flush();
		em.refresh(t);
		return t;
	}
 
	...
}

Le WSDL est bien généré et j'appelle le service "CreateThirdpartyRequest" avec SoapUI en précisant un paramètre "name".

Or une exception est générée :

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
 
javax.persistence.TransactionRequiredException: no transaction is in progress
        at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:792)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
        at $Proxy240.flush(Unknown Source)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
        at $Proxy232.flush(Unknown Source)
        at fr.company.compta.business.data.access.impl.GenericDaoImpl.create(GenericDaoImpl.java:25)
        at fr.company.compta.business.data.access.impl.ThirdpartyDaoImpl.create(ThirdpartyDaoImpl.java:21)
        at fr.company.compta.business.service.logic.impl.ThirdpartyServiceImpl.createThirdparty(ThirdpartyServiceImpl.java:25)
        at fr.company.compta.business.web.endpoint.BasicEndpoint.createThirdpartyRequest(BasicEndpoint.java:40)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.springframework.ws.server.endpoint.MethodEndpoint.invoke(MethodEndpoint.java:132)
        at org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter.invokeInternal(DefaultMethodEndpointAdapter.java:229)
        at org.springframework.ws.server.endpoint.adapter.AbstractMethodEndpointAdapter.invoke(AbstractMethodEndpointAdapter.java:53)
        at org.springframework.ws.server.MessageDispatcher.dispatch(MessageDispatcher.java:231)
        at org.springframework.ws.server.MessageDispatcher.receive(MessageDispatcher.java:172)
        at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:88)
        at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle(WebServiceMessageReceiverHandlerAdapter.java:57)
        at org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:222)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:851)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
        at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:257)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
        at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1764)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:662)


Je pense avoir mal configuré le transactionManager ou bien mal annoté mes classes et méthodes ... Qu'en pensez vous ?

Merci à vous