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
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
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>
Mon point d'entrée est un web service, d'où la présence d'un 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 <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>
web.xml
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.
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>
Et bien sûr cette dernière utilise l'entityManager configuré.
Endpoint : appel de "createThirdpartyRequest" via SOAP UI
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
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); } }
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
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 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 @Service("ThirdpartyDao") public class ThirdpartyDaoImpl implements ThirdpartyDao { @Autowired private GenericDao dao; @Override public void create(Thirdparty thirdparty) { dao.create(thirdparty); } ... }
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
Partager